State management can be accomplished in different ways:
useState
)Generally, smaller projects will be fine with just using local state. Larger projects may benefit from having a central state management system like Redux. Practically, you'll find that a combination of both will be best. Local state for components that contain data that is not important to any other parts of your app. Redux for data that needs to be shared across the app.
Redux is a state management library for web applications and works especially well with React. Redux integrations are provided via the fusion-plugin-react-redux plugin. For debugging, the plugin supports redux-devtools-extension
out of the box.
In addition to the plugin itself, fusion-plugin-react-redux
exports a handful of tokens that can be used to customize the Redux setup.
// The plugin itself
app.register(ReduxToken, ReactReduxPlugin);
// Root reducer
app.register(ReducerToken, reduxOptions.reducer);
// Any special enhancers for the Redux store
app.register(EnhancerToken, ActionEmitterEnhancerPlugin);
Under the hood, the plugin will set up a provider for you so you don't need to manually wrap your React tree with a provider. This occurs on both the client and the server and the plugin will handle hydration of the client side store. This means that any actions that fire on the server that change the current Redux state will be reflected on the client.
fusion-plugin-react-redux
expects a reducer to be registered to ReducerToken
. We can define that in src/redux.js
:
// src/redux.js
export default {
reducer: myReducer,
};
For example, given a state tree {count: 0}
that responds to an action {type: 'INCREMENT'}
, you would export this:
// src/redux.js
export default {
reducer: (state, action) => ({
count: state.count + (action.type === 'INCREMENT' ? 1 : 0),
}),
};
Note: Unlike the example above, you should typically refactor a root reducer so that each key in the state object is handled by its own reducer. See combineReducers
.
Use connect
from react-redux
to expose the Redux state to React props:
// src/components/root.js
import {connect} from 'react-redux';
const hoc = connect(
({count}) => ({count}), // copies state.count into props.count
dispatch => ({
// defines that props.increment dispatches a `INCREMENT` action
increment() {
dispatch({type: 'INCREMENT'});
},
})
);
const Component = ({count, increment}) => (
<button onClick={increment}>{count}</button>
);
export default hoc(Component);
If you need to add enhancers or middlewares, export them like this:
// src/redux.js
export default {
reducer,
enhancer: myEnhancer,
};