Flutter

[Flutter] 자식 위젯이 부모 위젯의 state 사용

hminor 2023. 7. 31. 16:17

자식 위젯이 부모 위젯의 state 사용

  • Props를 하는 방법의 단계
    1. 보내기
      • 전송할 클래스 즉 하위 위젯, 자식 위젯의 인자 값으로 이름: state 값 을 전송
        • ex) return Modal( 작명: 보낼 state값 );
    2. 등록하기
      • 받는 클래스에서 인자 값으로 state를 등록
      • 이후 변수 공간에 다시 한번 등록해주기
        • 여기서 JavaScript의 const 역할처럼 변하지 않는 변수 타입으로 Read-Only 만 할 경우엔 final을 붙여주면 된다.
    3. 사용하기
      • 그냥 사용하기
  • 현재는 title을 전송해서 Contact라는 변수를 하위 클래스로 전달 후 사용하는 코드 작성
import 'package:flutter/material.dart';

void main() {
  runApp(
      MaterialApp(
        home: MyApp()
      )
  );
}

class MyApp extends StatefulWidget {
  MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  var a = 1;
  var name = ['메시', '날강두', '홀란'];
  var cnt = [0, 0, 0];
  var title = 'Contact';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          showDialog(context: context, builder: (context){
            return Dialog(
              child: Modal(state: title)
            );
          });
        },
      ),
      appBar: AppBar(),
      body: ListView.builder(
          itemCount: 3,
          itemBuilder: (c,i){
            return ListTile(
              leading: Text(cnt[i].toString()),
              title: Text(name[i]),
              trailing: TextButton(
                child: Text('좋아요'),
                onPressed: (){
                  setState(() {
                    cnt[i]++;
                  });
                },
              ),
            );
          }
      ),
    );
  }
}

class Modal extends StatelessWidget {
  const Modal({super.key, this.state});
  final state;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 400,
      margin: EdgeInsets.fromLTRB(30, 0, 30, 0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            margin: EdgeInsets.all(30),
            child: Text(state, style: TextStyle(fontSize: 40, fontWeight: FontWeight.w900)),
          ),
          Container(
            margin: EdgeInsets.all(30),
            child: TextField(style: TextStyle(fontSize: 30),),
          ),
          Container(
            margin: EdgeInsets.all(30),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                Container(
                  margin: EdgeInsets.fromLTRB(20, 0, 20, 0),
                  child: TextButton(onPressed: (){
                    Navigator.pop(context);
                  }, child: Text('Cencel', style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),)),
                ),
                Container(
                  margin: EdgeInsets.fromLTRB(20, 0, 20, 0),
                  child: TextButton(onPressed: (){

                  }, child: Text('OK', style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),)),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}
  • 여기서 궁금점
    • const Modal({super.key, this.state});
    • 위의 코드에서 중괄호를 사용하는 이유는 선택적으로 하나만 전송해도 받아준다는 의미가 된다.

숙제

  • 하위 클래스에서 상위 클래스의 state 값을 변경하고자 하는 코드를 작성하기
  • 순서
    • 아래 코드처럼 상위 클래스 내에서 변경 메서드를 만들기
    • 변경 메서드를 하위 클래스에서 등록하기
    • 변경 메서드 사용하기
import 'package:flutter/material.dart';

void main() {
  runApp(
      MaterialApp(
        home: MyApp()
      )
  );
}

class MyApp extends StatefulWidget {
  MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  var a = 1;
  var name = ['메시', '날강두', '홀란'];
  var cnt = [0, 0, 0];
  var title = 'Contact';

  changeNumber(){
    setState(() {
      a++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          showDialog(context: context, builder: (context){
            return Dialog(
              child: Modal(state: title, changeNumber: changeNumber)
            );
          });
        },
      ),
      appBar: AppBar(title: Text(a.toString()),),
      body: ListView.builder(
          itemCount: 3,
          itemBuilder: (c,i){
            return ListTile(
              leading: Text(cnt[i].toString()),
              title: Text(name[i]),
              trailing: TextButton(
                child: Text('좋아요'),
                onPressed: (){
                  setState(() {
                    cnt[i]++;
                  });
                },
              ),
            );
          }
      ),
    );
  }
}

class Modal extends StatelessWidget {
  const Modal({super.key, this.state, this.changeNumber});
  final state;
  final changeNumber;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 400,
      margin: EdgeInsets.fromLTRB(30, 0, 30, 0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            margin: EdgeInsets.all(30),
            child: Text(state, style: TextStyle(fontSize: 40, fontWeight: FontWeight.w900)),
          ),
          Container(
            margin: EdgeInsets.all(30),
            child: TextField(style: TextStyle(fontSize: 30),),
          ),
          Container(
            margin: EdgeInsets.all(30),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                Container(
                  margin: EdgeInsets.fromLTRB(20, 0, 20, 0),
                  child: TextButton(onPressed: (){
                    Navigator.pop(context);
                  }, child: Text('Cencel', style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),)),
                ),
                Container(
                  margin: EdgeInsets.fromLTRB(20, 0, 20, 0),
                  child: TextButton(onPressed: (){
                    changeNumber();
                  }, child: Text('OK', style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),)),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}