To keep my app as performant as possible and code testable and maintainable i read about normalizing the redux state: https://redux.js.org/recipes/structuringreducers/normalizingstateshape
I was wondering if something like this is possible with redux in flutter. I have this state and view model:
class CompetitionState {
final LoadingStatus status;
final Competition competition;
}
class Competition {
final List<Competitor> competitors;
}
class CompetitionPageViewModel {
final LoadingStatus status;
final Competition competition;
}
A single competitor inside the List
of competitors can change dynamically based on user input or socket events. Currently a change inside one competitor would lead to a complete rerender of my ListView
as i connect the view model like this:
return StoreConnector<AppState, CompetitionPageViewModel>(
distinct: true,
converter: (store) => CompetitionPageViewModel.fromStore(store),
builder: (context, viewModel) => CompetitionPageContent(viewModel)
);
Is there a solution to this problem? My first approach would be to also normalize the state by introducing an EntityState, which holds all the different normalized entites. Similiar to how it is displayed here: https://medium.com/statuscode/dissecting-twitters-redux-store-d7280b62c6b1#.2e55tu6wb
But with this i am unsure how to structure the state and the reducers to be able to work on single entities without causing a complete list rerender. And also how to connect a Widget to a single entity inside this state. Has anyone any expierence with this and can guide me in a direction?
First of all, normalizing state is simply a paradigm so it is applicable in any form of state management. The first thing you need to normalize your state is some way to uniquely identify the model you want to normalize (most likely an ID), in this case the Competitor
. You can follow the EntityState example that you linked to to accomplish this. Basically you would just store a mapping of id
to Competitor
somewhere in your state. Then, you would change your Competition
class to:
class Competition {
final List<int> competitorIds;
}
And then, in your Flutter ListView you can attach each competitor to its own StoreConnector
like so:
ListView.builder(
itemCount: competition.competitorIds.length,
itemBuilder: (context, index) {
int competitorId = competition.competitorIds[index];
return StoreConnector<AppState, Competitor>(
distinct: true,
converter: (store) => store.state.entities.allCompetitors[competitorId],
builder: ...
);
}
)