as far as I understood Redux it is about keeping all state of the UI in one store (to be able to reproduce certain states easily and to have no side-effects). You can manipulate the state via triggering actions which trigger reducers.
I am currently writing a small blog-like app where you can simply create and edit posts. I have a dialog for creating a post, roughly the render
method of the App
ponent returns something like this:
<div>
<AppBar ... />
<PostFormDialog
addPost={actions.addPost}
ref="postFormDialog" />
<PostList
posts={posts}
actions={actions} />
</div>
My question is: should the state of the dialog (opened or closed) be part of the state object of the App ponent? And should therefore opening and closing the dialog be triggered via an action instead of doing something like the following:
onTriggerCreatePostDialog(e) {
this.refs.postFormDialog.show();
}
where onTriggerCreatePostDialog
is triggered via some click listener on a "create" button or so.
It seems a little bit strange to me to do it via an actions because is introduces kind of an "indirection".
However, assuming that I want to reuse the dialog for the edit action, I must be able to open the dialog from elements which are deeper in the ponent structure, for example from a Post
ponent which is a child of the PostList
ponent. What I could do is pass the onTriggerCreatePostDialog
function down the hierarchy via the props
property, but that seems cumbersome to me...
So int the end is is also about municating between ponents which are not in a direct parent-child relationship. Are there other options? Should I somehow utilise a global event bus? I am quite unsure currently.
as far as I understood Redux it is about keeping all state of the UI in one store (to be able to reproduce certain states easily and to have no side-effects). You can manipulate the state via triggering actions which trigger reducers.
I am currently writing a small blog-like app where you can simply create and edit posts. I have a dialog for creating a post, roughly the render
method of the App
ponent returns something like this:
<div>
<AppBar ... />
<PostFormDialog
addPost={actions.addPost}
ref="postFormDialog" />
<PostList
posts={posts}
actions={actions} />
</div>
My question is: should the state of the dialog (opened or closed) be part of the state object of the App ponent? And should therefore opening and closing the dialog be triggered via an action instead of doing something like the following:
onTriggerCreatePostDialog(e) {
this.refs.postFormDialog.show();
}
where onTriggerCreatePostDialog
is triggered via some click listener on a "create" button or so.
It seems a little bit strange to me to do it via an actions because is introduces kind of an "indirection".
However, assuming that I want to reuse the dialog for the edit action, I must be able to open the dialog from elements which are deeper in the ponent structure, for example from a Post
ponent which is a child of the PostList
ponent. What I could do is pass the onTriggerCreatePostDialog
function down the hierarchy via the props
property, but that seems cumbersome to me...
So int the end is is also about municating between ponents which are not in a direct parent-child relationship. Are there other options? Should I somehow utilise a global event bus? I am quite unsure currently.
Share Improve this question asked Nov 6, 2015 at 15:28 B zum SB zum S 2583 silver badges10 bronze badges2 Answers
Reset to default 7It seems to me that you are on the right path. The docs can be a bit tricky at first, but I can tell you how my team and I are using the implementation.
To address your first question; if the state is specific to a ponent then we keep that state with the ponent. An example of this would be a panel that pages records locally --- nothing else needs to be aware of that behavior. So in this instance we wouldn't trigger a redux action when the page changed, that would be handled internally within the ponent structure using refs.
Our redux state is prised primarily of data collected via xhr requests or from a shared state. An example of shared state would be managing a time range among multiple ponents that use that range to display data. In this instance we would trigger a redux action; update the date state with whatever it was changed to (while also updating some other state items via xhr) and then ultimately that gets back to the ponents and they re-render.
With that said, triggering actions via refs is totally acceptable, it's just about what the specific use case is.
To address your second question; redux remends using the Smart & Dumb ponent concept. So you are right that you would pass a function down the tree for the dumb ponents to utilize.
We utilize mapDispatchToProps in our connect setup. So basically you pass a function that returns an object of function "dispatchers". You will be able to access those functions directly in your smart ponent's this.props
.
Example of mapDispatchToProps
function mapDispatchToProps(dispatch) {
return {
myAction: () => dispatch(actions.myAction()),
};
}
So that works 99% of the time, but I've run into some corner cases where we do use a global event bus, so don't be afraid to utilize both while attempting to stick to the Smart / Dumb ponent method as much as possible.
As a side note, I would remend using reselect to map your redux state to the smart ponent. You can also find other great redux resources here (there are several things listed that we use).
The state for the dialog should be in the redux store, triggered by actions. whether it should be rendered should be determined by checking that state in the redux store.
App.render()
should be something like this:
render() {
const { showDialog } = this.props;
return (
<div>
<AppBar ... />
{ showDialog ? <PostFormDialog ... /> : false }
<PostList ... />
</div>
);
}
where mapStateToProps
would be something like state => {{ showDialog: state.showDialog }}
In terms of delivering the action creator, passing it down the props tree is probably the correct way to do it unless you have some good location where it makes sense to have another smart ponent.