How to replace bindActionCreators and to use mapDispatchToProps and mapStateToProps - reactjs

We are calling an API using bindActionCreators and every time I need to use this.props to post and to get data.
The problem is that I need to store the response data in some variable and access it through this.props.variable. For example:
export default withStyles(styles, { withTheme: true })(connect(
state => state.sensi,
dispatch => bindActionCreators(actionCreators, dispatch)
)(FetchSensi));
How can I do it?

mapStateToProps
const mapStateToProps = state => ({
variableName: state.someVariableFromState
});
and i don't use mapDispatchToProps, i pass directly action to connect like this
import {action1, action2} from './someActionFolder';
export default connect(mapStateToProps, {action1, action2})(YourComponent);
and inside your component you can use your actions like
this.props.action1();
this.props.action2();
you can also combine all your actions like
import * as actions from './yourActionsFolder';
export default connect(mapStateToProps, actions);

Related

React Problem with multiple export in Class Component

Previously in my Class Component redux connect used to look something like this. This worked without any issues.
//File: MyComponent.jsx
//in below code this.props.selectProducts is not undefined and this works fine
const mapStateToProps = null;
const mapActionsToProps = {
selectProducts
};
export default connect(
mapStateToProps,
mapActionsToProps
)(MyComponent);
After this I had to use this component called notistack to display the snackbar and I exported this as default instead of the existing redux connect. Now I am facing a issue where the props doesn't exist.
const mapStateToProps = null;
const mapActionsToProps = {
selectProducts
};
//Now this.props.selectProducts is undefined which is part of redux store
//But this.props.enqueueSnackbar("Preference saved."); this works. which is part of withSnackbar
export const ConnectedList = connect(
mapStateToProps,
mapActionsToProps
)(MyComponent);
export default withSnackbar(MyComponent);
If i make the redux connect as default I am unable to access this.props.enqueueSnackbar(). Any help would be much appreciated. Thanks
Just use withSnackbar on the component returned by connect and use that:
const ConnectedList = connect(
mapStateToProps,
mapActionsToProps
)(MyComponent);
export default withSnackbar(ConnectedList);

mapDispatchToProps doesn't add actions to component

I'm tryng to use connect like in Redux docs (here) and I'm also using redux toolkit to work with redux (link)
import { connect } from 'react-redux'
import { actions } from '../../redux/actions';
import FormComponent from './Form';
const mapStateToProps = (state: any) => ({
item: 'state.item'
})
const mapDispatchToProps = { actions }
export default connect(
mapStateToProps,
mapDispatchToProps
)(FormComponent)
In my FormComponent I'm getting item props from mapStateToProps but actions are not passed down
My actions look like this
import { createAction } from '#reduxjs/toolkit';
const registerUser = createAction<Object, 'REGISTER_USER'>('REGISTER_USER');
export const actions = {
registerUser
}
And if I do console.log(actions) it is an object with function.
All the help will be appreciated.
This line:
mapDispatchToProps = { actions }
Is the equivalent to:
mapDispatchToProps = {
actions: {
registerUser
}
}
As per the docs bindActionCreators expects an object hash of action creators. In this example, you have nested yours under an actions property which (based on the source) will result in them being excluded from the returned props.
If you want the actions to be accessible directly from props then you can set mapDispatchToProps = actions, or just pass actions directly into connect e.g.
connect(mapStateToProps, actions)(FormComponent)

How to not use bindActionCreators in mapdispatchtoprops?

I don't want to use bindActionCreators in mapdispatchtoprops. What is the other way to dispatch action?
I am accessing it in componentdidmount() like below:
````````
this.props.getEntityData.getEntitiesAction().then({})
dispatching it as below:
`````
const mapDispatchToProps = (dispatch) => {
return {
getEntityData : bindActionCreators(getEntitiesAction, dispatch)
};
```````````
This is working and I am getting the data.
But I don't want to use nindActionCreators. What is the other way to
dispatch action and how can I access it in in componentdidmount?
From the docs:
The only use case for bindActionCreators is when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass dispatch or the Redux store to it.
You can import the action and pass it to the component through connect, like this:
import {action} from './actions';
...
componentDidMount() {
this.props.action();
}
...
connect(mapStateToProps, {action})(Component)
If you don't need the store you can just pass in null instead of mapStateToProps.

Multiple actionCreators in single component

I want to have multiple actionCreators dispatched into one component. I know you can do this with state
export default connect(
(state: ApplicationState) => Object.assign({}, state.search, state.resources),
ResourcesState.actionCreators// i have another actionCreator I want to add
)(Home) as typeof Home;
But not sure the syntax to do this with actionCreators. I have read into
mapDispatchToProps
But not sure how to implement.
There are a few ways to set up dispatching of Redux actions in React components:
Use connect(mapState)(MyComponent). By default, your component will be given props.dispatch, and you can call props.dispatch({type : "SOME_ACTION"}).
Pass a mapDispatchToProps function as the second argument to connect. Inside, you can create new function references that call dispatch:
function mapDispatchToProps(dispatch) {
return {
addTodo : (text) => dispatch({type : "ADD_TODO", text})
}
}
You can also use the Redux bindActionCreators utility instead:
function mapDispatchToProps(dispatch) {
return bindActionCreators({addTodo, toggleTodo}, dispatch);
}
Finally, you can pass an object full of action creators directly to connect:
const actions = {addTodo, toggleTodo};
export default connect(mapState, actions)(MyComponent);
I highly recommend the fourth approach, which I also talk about in my blog post Idiomatic Redux: Why Use Action Creators?.
mapDispatchToProps is the second argument in connect. So for example:
import customAction from 'actions-directory-in-your-app'
const mapStateToProps = () => {} // no implementing anything for example purposes
const mapDispatchToProps = () => ({ customAction })
const ConnectedContainer = connect(
mapStateToProps,
mapDispatchToProps
)(YourContainer)
customAction becomes now a prop in YourContainer so you can use it the same way other props within your component.
the Second argument to connect takes an object or a function so you can add
export default connect(
(state: ApplicationState) => Object.assign({}, state.search, state.resources),
{
ResourcesState.actionCreators,
some_other_action_creators,
some_more
}
)(Home) as typeof Home;
Also read through this answer on Stackoverflow for more information on how to use action creators
Why is there no need for a mapDispatchToProps function here?
The second argument to connect takes an object, so you can use of ES6 syntax and avoid the use of mapDispatchToProps.
import { yourAction } from './your_actions_folder'
class Home extends Component{
....
//For dispatch a action you only call the action Creator
this.props.yourAction()
}
export default connect(mapStateToProps,{yourAction})(Home)

Map redux dispatch to redux-form

Sorry if this has been answered elsewhere, I'm a Redux beginner, and I couldn't find anything related.
I'm having trouble mapping dispatch to ReduxForm. Im setting up my reducers like this:
import { reducer as formReducer } from 'redux-form';
import foo from './foo';
import bar from './bar';
const rootReducer = combineReducers({
foo,
bar,
form: formReducer
});
export default rootReducer;
and then combining them like so:
import rootReducer from '../reducers/index';
const loggerMiddleware = createLogger();
const createStoreWithMiddlware = applyMiddleware(
thunkMiddleware,
loggerMiddleware
)(createStore);
export default function configureStore(initialState) {
const store = createStoreWithMiddlware(rootReducer, initialState);
return store;
}
and then mapping dispatch to props like this:
function mapStateToProps(state) {
return {
foo: state.foo,
bar: state.bar
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(App)
And then I have a form component that I am wrapping in a reduxForm like this:
TestForm = reduxForm({
form: 'testForm',
fields: ['firstName', 'lastName', 'email']
})(TestForm);
export default TestForm;
But I get an error:
Warning: Failed propType: Required prop dispatch was not specified in ReduxForm(TestForm). Check the render method of TestFormParent.
What is the best way to inject dispatch into a form component?
Turns out the docs on npm are a little bit different, and more complete. If anyone else runs into this issue, use connectReduxForm instead of reduxForm solved the problem.
reduxForm works for version 4 of redux-form

Resources