Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

Flutter/Flutter Study

React Native에서 Flutter로 갈아타기 #7 - State management

방피터 2022. 10. 6. 15:50

Provider! 이게 우리가 flutter에서 할거야.

Provider는 State management 패키지야. React에서 Redux라고 불렀던 그것 비슷한 것이지. 심플하게 말하자면 전역적으로 관리되는 state management? 정도 될거 같은데? 사실 나는 Redux는 모르고 Recoil만 사용했었는데 ㅋㅋㅋ 뭐 전역 변수 관리 툴이 그게 그거겠지 ㅋㅋㅋㅋ

암튼 Recoil에 대해서는 아래 글 참고하시고 ㅋ

2022.05.24 - [React Native] - Recoil 가장 기본적인 사용법

 

Recoil 가장 기본적인 사용법

난 최근에 React native를 시작해서 그런지 왠만하면 최신 라이브러리를 사용하고 싶더라고~ 그래서 상태 관리 라이브러리도 가장 최근에 나온 Recoil을 사용하고 있어. Redux가 가장 유명한 거 같은데

engschool.tistory.com

저번에도 말했지만 Flutter 문서에서 Flutter 모르면 나대지 말고 Provider 쓰라고 되어 있어ㅋㅋㅋㅋ 그러니까 쓰자구.

나대지 말고 provider 써라.

우선 설치부터!

%flutter pub add provider

아니면 pubspec.yaml에 아래와 같이 provider 추가하고 flutter pub get 명령으로 설치.

dependencies:
  flutter:
    sdk: flutter

  provider: ^6.0.0

설치가 끝났으면 시작해보자구.

우선 provider를 사용하기 위해 알아야 할 건 3가지!

  • ChangeNotifier :  다른 위젯이 구독 가능한 State를 가지고 있는 위젯
  • ChangeNotifierProvider : ChangeNotifier 인스턴스를 자식 위젯에게 전달하는 위젯
  • Consumer : State를 전달받는 위젯

자 그러면 저 계속했왔던 Counter 예제를 Provider를 사용해서 만들어보자구.👇👇

void main() {
  runApp(ChangeNotifierProvider(
      create: (context) => Counter(), child: const MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(title: Text("테스트~")),
      body: Center(
        child: AddSub(),
      ),
    ));
  }
}

먼저 main에서 전체를 ChangeNotifierProvider로 감싸주고 create에 생성할 ChangeNotifier를 등록, child에 내 앱 등록.

그 다음에는 Counter라는 이름의 ChangeNorifier를 만들어 봅시다.👇👇

// Counter ChangeNotifier
class Counter with ChangeNotifier {
  int value = 0;

  void increment() {
    value += 1;
    notifyListeners();
  }

  void decrement() {
    value -= 1;
    notifyListeners();
  }
}

Counter 안에는 value가 있고 그 값을 변경시킬 수 있는 함수가 선언되어 있어. 그럼 하나 남았네? Consumer! 만들어보자구.👇

class AddSub extends StatelessWidget {
  const AddSub({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Consumer<Counter>(builder: ((context, counter, child) {
      //counter가 Counter의 인스턴스임.
        return Column(
          children: [
            Text('${counter.value}'),
            TextButton(
              child: Text("add"),
              onPressed: () => counter.increment(),//arrow 함수로 이렇게 물려도 되고
            ),
            TextButton(
              child: Text("sub"),
              onPressed: counter.decrement,//함수 포인터만 물려도 동작할거 같아서 해봤더니 됨!
            ),
          ],
        );
      })),
    );
  }
}

State는 외부에 있으니까 버튼 위젯에서는 부담없이 StatelessWidget으로 선언하고 Container 위젯 안에서 Consumer<Counter>를 child로 등록하면 돼.  그리고 자식 요소에서는 builder에 두 번째 요소가 Counter의 인스턴스니까 저걸 가지고 와서 사용하면 되지. counter.value, counter.increment(), counter.decrement() 이렇게. 기타 Consumer 사용법은 코드를 참고해~ 왜 저렇게 해야 하냐고 묻지마 ㅋ 그냥 구글이 저렇게 만든거야.

그리고 마지막 한가지 더. 저렇게 ChangeNotifier로 선언된 Counter는 자식 위젯의 Consumer뿐만 아니라 ChangeNotifierProvider로 감싸진 모든 곳에서 사용이 가능해.

아래와 같이 MyApp의 body에 floatingActionButton을 하나 넣고 그 안에서 Counter를 사용할 수 있는지 확인해봤어👇👇

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(title: Text("테스트~")),
      body: Center(
        child: AddSub(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          var counter = context.read<Counter>();//자식 위젯이 아니라도 이렇게 읽어올 수 있다.
          counter.increment();
        },
        child: const Text("더하기"),
      ),
    ));
  }
}

사용법은 간단 context.read<Counter>() 메소드를 통해서 얻은 counter인스턴스를 통해 state를 관리할 수 있었어. 음 난 redux는 경험이 없고 recoil을 사용했었다고 그랬잖아? recoil이랑 비교하자면 뭐 사용법은 거부감없이 비슷한 것 같아. 더 쉬운거 같기도 하고.

테스트가 잘 되는 걸 확인할 수 있다.(사소한 건 신경쓰지 말자.)

물론 더 복잡한 앱 제작하다보면 이 정도로 간단하게 되지 않겠지 ㅋㅋ 그래도 계속 열심히 하면 되겠지 ㅎㅎㅎ 이제 각 페이지들 routing하는 navigation 이랑, login, firebase firestore 정도 붙여보고 나서 본격적으로 앱을 하나 만들어봐야겠어. 다들 힘내라고! 안녕!

 
반응형