Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onInit does not triggers state change #8

Closed
lasseschmitt opened this issue Feb 14, 2018 · 4 comments
Closed

onInit does not triggers state change #8

lasseschmitt opened this issue Feb 14, 2018 · 4 comments

Comments

@lasseschmitt
Copy link

Hey @brianegan

first of all thanks for the awesome library!!!

I noticed the following:
Im having an app state requestLessonState which is on app launch null. onInit I would like to dispatch an action to assign requestLessonState a value, in this case false. The action get dispatched as expected and the state changed to the expected value. BUT the view model get generated before the state changed. So for me it is not possible to basically create an init value for the model.

Is this an issue or an expected behaviour (something async or so)? If it is an expected behaviour, do you something in mind to solve this "issue"?

I hope you can help me some how or push me in the right direction.

Thanks in advance

Imagine the following setup

Main App State

@immutable
class AppState {

  final RequestLessonState requestLessonState;

  AppState({
    this.requestLessonState,
  });

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

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

Sub App State

@immutable
class RequestLessonState {
  final bool dropOffIsDifferent;
  
  RequestLessonState({
      this.dropOffIsDifferent,
  });

  RequestLessonState copyWith({
     String dropOffLocation,
  }) {

    return new RequestLessonState(
        dropOffIsDifferent: dropOffIsDifferent ?? this.dropOffIsDifferent,
    );
  }

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

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

Widget

class CreateLessonScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new StoreConnector<AppState, _ViewModel>(
      onInit: (store) => store.dispatch(new InitRequestLessonAction()),
      distinct: true,
      converter: _ViewModel.fromStore,
      builder: (context, vm) {
        return new Scaffold(
            appBar: new AppBar(),
            body: new SafeArea(
                  bottom: true,
                  child: new Column(
                    children: <Widget>[
                      new Switch(value: vm.dropOfIsDifferent, onChanged: (value){}),
                    ],
                  ),
                ),
        );
      },
    );
  }
}

My View Model

class _ViewModel {

  final bool dropOfIsDifferent;
  
  _ViewModel({
    this.dropOfIsDifferent,
 
  });

  static _ViewModel fromStore(Store<AppState> store) {
      return new _ViewModel(
          dropOfIsDifferent: store.state.requestLessonState.dropOffIsDifferent,
      );
  }

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

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

Action

class InitRequestLessonAction {
  InitRequestLessonAction();

  @override
  String toString() {
    return 'InitRequestLessonAction{}';
  }
}

Reducer

// the main reducer 
AppState appReducer(AppState state, action) {
  return new AppState(
      requestLessonState: requestLessonReducer(state.requestLessonState, action),
  );
}


final requestLessonReducer = combineTypedReducers<RequestLessonState>([
  new ReducerBinding<RequestLessonState, InitRequestLessonAction>(_setInitRequestLessonAction),
]);

RequestLessonState _setInitRequestLessonAction(RequestLessonState state, InitRequestLessonAction action) {
  return new RequestLessonState(dropOffIsDifferent: false);
}
@brianegan
Copy link
Owner

brianegan commented Feb 14, 2018

Hey hey, thanks so much for the detailed report.

You're not doing anything wrong, but you have found a bug!!! :) You should definitely be able to dispatch either sync or async actions freely from within the onInit function. I had accidentally only tested async cases...

I've written a test case for this bug and verified it's failing. I've got a fix in the works and I'll push it up soon!

Thanks again.

brianegan added a commit that referenced this issue Feb 14, 2018
This allows users to dispatch sync actions within the onInit function.

Fixes #8
@brianegan
Copy link
Owner

New package published as 0.3.5 with this bugfix :)

@brianegan
Copy link
Owner

@driveddy Just to confirm, did this bugfix work for ya?

@lasseschmitt
Copy link
Author

@brianegan Yes like a charm. Thanks you so much for your quick fix!! ❤

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants