So i'm writing a React-Redux web app, and i call dispatch from my react components like this :
this.props.dispatch(someAction());
Now i need to call dispatch from a javascript function that is not a React Component, so how do i import the dispatch function and use it in this case ?
Thank you.
The dispatch function is a member of your redux store. If you created and exported your store in a module, it would be as easy as importing the store in your module and calling the dispatch function.
Example:
// store.js
import { createStore } from 'redux'
export default createStore(reducers)
// somefile.js
import store from './store'
store.dispatch(someAction)
The dispatch method is one of the store's methods. react-redux makes dispatch available to components as props via the provider, and mapDispatchToProps.
You can dispatch directly from the store:
store.dispatch(action)
Related
I have a store that needs to connect to different components. I created 3 different slices and wanted to make a dependency with the store.
When I hook all of three reducers :
export const store = configureStore({
reducer : {
home : homeSlice,
about : aboutSlice,
review : reviewSlice,
},
});
I get the next error :
Invalid hook call. Hooks can only be called inside of the body of a function component.
You are somehow using store incorrectly.
The Store needs to be passed to the Provider (which wraps all the components inside app.js).
import {store} from 'your_path'
const App = () => (
<Provider store={store}>
<MyApplication />
</Provider>
)
After that, you can already use Redux inside components.
To change states, use the useDispatch() hook,
and to get the state useSelector().
Here is a link to documentation about hooks in React-Redux https://react-redux.js.org/api/hooks
As in react, documentation hooks can be called only inside of a functional component. The code you provide to merge reducers is correct. You need to use useSelector and useDispatch hooks inside the component functions to retrieve the value or dispatch an action respectively. What is the main issue you are facing?
I am using redux in a phaser and react based game, dispatching actions in React Components, Utils, and Axios API Calls. I know there are useDispatch hook and connect can be used for React Components, however, based on my own experience, I can use dispatch from store directly as well.
import store from 'my-redux/store';
const { dispatch } = store;
dispatch(actionCreator(1));
I use the above way to dispatch actions in Phaser Scene and Utils to change states such as health and score, and dispatch actions in Axios async API calls. It is convenient and light compare to using useDispatch or connect, so why is it not recommended to dispatch from store except for isomorphic app?
Reference for why not use dispatch from store for isomorphic apps:
redux issue!916
redux issue!184
redux issue!362
I even want to bind dispatch to action creators like this:
import store from 'my-redux/store';
const { dispatch } = store;
export const handleSetSomeThing = (state) => {
const action = {
type: ActionTypes.SOME_TYPE,
payload: state,
};
dispatch(action);
};
Then I can call the above function like this without importing store or using connect, redux hook:
handleSetSomeThing({ health: 5 })
Any idea?
I want to use nextjs in my new project with redux and thunk also. I wondering how to implement all packages correctly.
In my previous projects pages has HOC components like:
import {connect} from 'react-redux';
import Page from './about';
import {fetchUsers} from '../../actions/user';
const mapStateToProps = (state) => {
const {users} = state;
return users;
};
const mapDispatchToProps = (dispatch) => {
return {
fetchUsers: () => dispatch(fetchUsers())
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Page);
And method to fetch users I implemented in componentDidMount
How to implement the same logic for nexjs?
What have I do?
Implemented store (base on next-redux-wrapper in _app.js)
Created HOC component (like below) with mapStateToProps and
mapDispatchToProps
Currently I thinking about use somehow this.props.fetchUsers method into getInitialProps - documentation say that this method should be used to fetch data before render site.
Please help me with correctly redux implementation for nextjs
You can follow this example
The correct way is to pass the store to the getInitialProps context and to the App component so you can pass it to the Provider.
The getInitialProps can't access to instance of the component, this is not accessible, so you can't call this.props.fetchUsers, but, because you are passing store to its context, you can do store.dispatch(fetchUsers()) and remove dispatch from mapDispatchToProps.
Generally I dispatch actions in getInitialProps and then map state to props within connect.
i have a file inside action directory which is root.js.
Root.js will compile all the others action inside, and i bind it with bindActionCreators
export const all = (store) => {
AUTH: bindActionCreators(AUTH.actions, store.dispatch),
....: .....
}
From what i learned, bindActionCreators is for the purpose of auto dispatching the action.
If that is the case, then how do i access it from smart component?
I see things like dispatch(action). But since now i already bind it globally, i dont think that i would need to specify dispatch anymore. How do i do it, or is there any part that i misunderstood?
Thank you
bindActionCreators - will create an object of actions each wrapped with the dispatch.
It's good for passing them as refs to non-connected components that should not know anything about redux or dispatch.
Quote 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.
So if you want that connected component to pass action creators to a dumb component, you can set an object via bindActionCreators and pass it with props to the dumb component.
Example:
const myActionCreators = bindActionCreators(Auth.myActions, dispatch)
<DumbComponent {...myActionCreators} />
The recommended approach is to have each connected component file import the action creators it needs, and use the "object shorthand" supported by connect:
import {addTodo, toggleTodo} from "./todoActions";
const actions = {addTodo, toggleTodo};
export default connect(null, actions)(TodoList);
// each TodoList instance now has this.props.addTodo and
// this.props.toggleTodo, which will dispatch actions when called.
I am using React and Redux.
I have a banner component where banners are shown in a carousel.
I have BannerContainer.js which is connected to redux and Banner.js which is component.
On click of a carousel, I need to do 2 things
Redirect user to another url'
Fire a GTM event
None of the above actions modify the state. Should I pass an onClick handler via mapDispatchToProps from my container?
What should be the correct way?
If you don't need to dispatch any action, I don't think you need to pass the function in mapDispatchToProps. A local function inside BannerContainer should be enough for you requirements. BTW, what is GTM event? I don't know the abbr.
I would still pass that in connect, because that's business logic that shouldn't be hidden down your component tree. Otherwise if you need to change the GTM stuff or change routes you will have to find the component.
Create a thunk action creator that performs your side-effects and map it using mapDispatchToProps. If your component is not a top-level Route component, you can use withRouter to get access to the routing context. You can even compose both decorators or enhancers into own in your container:
import { connect, compose } from 'redux'
import { withRouter } from 'react-router'
import YourComponent from '../components/YourComponent'
// your dispatch
const mapDispatchToProps = (dispatch, ownProps) => {
return {
onBannerClick(e){
//do your GTM stuff
//redirect the user!
ownProps.history.push('/gohere')
}
}
}
// combine your enhancers, order is significant if you want
// to have withRouter() props in your connect methods
const enhance = compose(
withRouter(),
connect(mapStateToProps, mapDispatchToProps),
)
export default enhance(YourComponent)