marcglasberg / async_redux

Flutter Package: A Redux version tailored for Flutter, which is easy to learn, to use, to test, and has no boilerplate. Allows for both sync and async reducers.
Other
230 stars 41 forks source link

my state is not changin #69

Closed mohammadameer closed 4 years ago

mohammadameer commented 4 years ago

I have a problem I can't find the bug my state is not changing

the main file

import 'package:Saree3/Graphql/client_provider.dart';
import 'package:Saree3/store/AppState.dart';
import 'package:async_redux/async_redux.dart';
import 'package:flutter/material.dart';
import 'package:Saree3/Constants/Constants.dart';
import 'package:Saree3/Screens/SplashScreen.dart';
import 'package:Saree3/Screens/HomeScreen.dart';
import 'package:Saree3/Screens/OtpScreen.dart';

Store<AppState> store;
void main() {
  var state = AppState.initialState();
  store = Store<AppState>(initialState: state);

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreProvider<AppState>(
      store: store,
      child: MaterialApp(
        // home: new Splash(),
        initialRoute: OTP_SCREEN,
        debugShowCheckedModeBanner: false,
        theme: new ThemeData(
          primaryColorDark: Colors.brown,
          primaryColor: Colors.blueAccent,
        ),
        routes: {
          HOME_SCREEN: (BuildContext context) => new HomeScreen(),
          OTP_SCREEN: (BuildContext context) => new OtpScreenConnector(),
        },
        builder: (context, child) {
          return Directionality(textDirection: TextDirection.rtl, child: child);
        },
      ),
    );
  }
}

OtpScreen

import 'package:Saree3/actions/User.dart';
import 'package:Saree3/store/AppState.dart';
import 'package:async_redux/async_redux.dart';
import 'package:flutter/material.dart';
import 'package:Saree3/Constants/Constants.dart';
import 'package:flutter/services.dart';

class OtpScreen extends StatefulWidget {
  final String firstName;
  final ValueChanged<String> signUp;

  OtpScreen({Key key, this.firstName, this.signUp}) : super(key: key);

  @override
  OtpScreenState createState() => OtpScreenState();
}

class OtpScreenState extends State<OtpScreen> {
  final _formKey = GlobalKey<FormState>();

  TextEditingController firstNameController;

  @override
  void initState() {
    super.initState();
    firstNameController = TextEditingController();
  }

  @override
  void dispose() {
    firstNameController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Form(
      key: _formKey,
      child: Container(
          padding: EdgeInsets.all(30),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextFormField(
                controller: firstNameController,
                onChanged: (text) {
                  // print(text);
                },
                autofocus: true,
                validator: (value) {
                  if (value.isEmpty) {
                    return 'لو سمحت املأ الفراغات';
                  }
                  return null;
                },
                decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: "الإسم الأول",
                    hintText: 'أدخل إسمك الأول'),
              ),
              SizedBox(
                height: 20,
              ),
              TextFormField(
                onChanged: (text) {
                  // print(text);
                },
                autofocus: true,
                validator: (value) {
                  if (value.isEmpty) {
                    return 'لو سمحت املأ الفراغات';
                  }
                  return null;
                },
                decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: "الإسم الثاني",
                    hintText: 'أدخل إسمك الثاني'),
              ),
              SizedBox(
                height: 20,
              ),
              TextFormField(
                keyboardType: TextInputType.number,
                inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
                onChanged: (text) {
                  // print(text);
                },
                autofocus: true,
                validator: (value) {
                  if (value.isEmpty) {
                    return 'لو سمحت املأ الفراغات';
                  }
                  return null;
                },
                decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: "رقم الجوال",
                    hintText: 'أدخل رقم الجوال'),
              ),
              Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  child: RaisedButton(
                    onPressed: () {
                      widget.signUp(firstNameController.text);
                    },
                    child: Text("تسجيل"),
                  )),
              Text('${widget.firstName}')
            ],
          )),
    ));
  }
}

class OtpScreenConnector extends StatelessWidget {
  OtpScreenConnector({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, ViewModel>(
      model: ViewModel(),
      builder: (BuildContext context, ViewModel vm) => OtpScreen(
        firstName: vm.firstName,
        signUp: vm.signUp,
      ),
    );
  }
}

class ViewModel extends BaseModel<AppState> {
  ViewModel();
  String firstName;
  ValueChanged<String> signUp;
  ViewModel.build({@required this.firstName, @required this.signUp});

  @override
  ViewModel fromStore() => ViewModel.build(
      firstName: state.userState.firstName,
      signUp: (String firstName) => dispatch(SignUp(firstName)));
}

the app state -- main state

import 'package:Saree3/store/UserState.dart';

class AppState {
  final UserState userState;

  AppState({this.userState});

  AppState copy({
    UserState userState,
  }) {
    return AppState(
      userState: userState ?? this.userState,
    );
  }

  static AppState initialState() =>
      AppState(userState: UserState.initialState());

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is AppState &&
          runtimeType == other.runtimeType &&
          userState == other.userState;

  @override
  int get hashCode => userState.hashCode;
}

var state = AppState.initialState();

user State

class UserState {
  final String firstName;
  UserState({this.firstName});

  UserState copy({String firstName}) =>
      UserState(firstName: firstName ?? this.firstName);

  static UserState initialState() => UserState(firstName: "mohammad");
  @override
  bool operator ==(other) =>
      identical(this, other) ||
      other is UserState &&
          runtimeType == other.runtimeType &&
          firstName == other.firstName;

  @override
  int get hashCode => firstName.hashCode;
}

tha signup action and reduce


import 'package:Saree3/store/AppState.dart';
import 'package:async_redux/async_redux.dart';

class SignUp extends ReduxAction<AppState> {
  final String firstName;

  SignUp(this.firstName);

  @override
  AppState reduce() =>
      state.copy(userState: state.userState.copy(firstName: firstName));
}
``
marcglasberg commented 4 years ago

You should list the observed states in the viewmodel builder super(equals: [ .......... ])

For example:

  ViewModel.build({
    @required this.firstName,
  }) : super(equals: [firstName]);

Otherwise it can't know when to rebuild.

Does this solve your problem?

mohammadameer commented 4 years ago

I was facing 2 problem :

1- The state is not changing

2- the ui is not changing

This fix the ui problem thanks 👍

But i still have the first problem

mohammadameer commented 4 years ago

everything is working now thanks