I have Material-ui and redux all set up in and working, however redux has you use connect with higher order components:
export default connect(mapStateToProps)(ComponentName);
while the Material-ui documentation has you do something similar:
export default muiThemeable()(ComponentName);
How would you combine the theme with the redux export to get them to export or work together?
You can compose multiple Higher Order Components:
export default muiThemeable()(connect(mapStateToProps)(ComponentName));
An HOC takes a component (and possibly other arguments) and returns another component. So, the return value of an HOC is a valid argument for another HOC.
Related
I don't know how to compose Redux with onClickOutside HOC in my component export...
I tried sth like this but didn't work
export default compose(
connect(null, mapDispatchToProps),
onClickOutside)
(DropMenu, clickOutsideConfig);
Error I got :
TypeError: Cannot read property 'isReactComponent' of undefined
You can solve this problem without using the redux compose method. Try something like the following:
export default connect(null, mapDispatchToProps)(onClickOutside(DropMenu))
Not sure what you're trying to do with the clickOutsideConfig, but you can always pass it in as props to DropMenu.
I am confused about why a create-react-app has both
import {store} from './our-redux-store'
const app = () => {
return (
<Provider store={store}>
<WholeAppGoesHere/>
</Provider>
)
}
versus using connect with a component like so:
import {connect} from 'react-redux';
class MyComp {
// ...
}
export default connect(
mapState,
mapDispatch
)(MyComponent);
do we need both? what's the difference?
The provider is a component. You use the provider at the top of the component chain where your application starts. You place it so it wraps your entire application. Within this container, you pass the store. This allows any child component to access the store.
connect() is used as a higher-order function that you wrap around specific components. Connect in essence maps state data contained within the store to the props within that specific component. Maybe it helps to think of connect() as a way an individual component gets the specific data it needs from the global store
Provider is a part of React Context functionality. By assigning your store there, it makes the specific value of store available to all consumers of that context.
connect() on the otherhand is a higher order component that injects your mapped states and dispatches into the props of your base component. To do so, it calls the Consumer part of this api to access the store context.
Edit: https://react-redux.js.org/using-react-redux/accessing-store#understanding-context-usage
In an application using react, redux and react-router, I'm using react-router-redux to issue navigation actions. I found that wrapping routes in a component with connect blocks navigation.
I made a sample with CodeSandbox that illustrates the issue: sample.
As is, the navigation doesn't work. However, if in ./components/Routes.jsx, this line:
export default connect(() => ({}), () => ({}))(Routes);
Is replaced by:
export default Routes;
It works.
Any idea how I could use connect in a component that wraps routes without breaking navigation?
See the troubleshooting section in react-redux docs.
If you change Routes.jsx export to:
export default connect(() => ({}), () => ({}), null, { pure: false })(Routes);
it will work.
This is because connect() implements shouldComponentUpdate by default,
assuming that your component will produce the same results given the
same props and state.
route changes, but props don't so the view doesn't update.
You could achieve same with withRouter hoc.
Not meant to be a duplicate.
I fixed it with withRouter like this
import { withRouter } from 'react-router-dom';
and
export default withRouter( connect(mapStateToProps)(App) );
See Redux, Router integration docs here
Have you ever encountered the warning message:
Warning: You cannot change <Router history>
Well use withRouter from react-router-dom
I have searched for this for so long because the Redux was recreating my App.jsx component which has <Route> </Route> as parents and this warning just freezes the routing in my app. I wanted to have React/Redux component, because I needed to pass authenticated props to the Route component, and redirect base on it, simple.
So import { withRouter } from 'react-router-dom'
and surround your component which is connected to redux with:
export default withRouter(connect(mapStateToProps)(App));
Something more:
Most of the times if you want to communicate with the router, takes some props, pass something else to it, get history, locations form it and you are using Redux in your app, surround this component with withRouter and you will have access to these properties as props.
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-redux for managing my presentation & container components. And i am passing a list of actions to my presentation component from my container component in the below manner :-
function mapDispatchToProps(dispatch) {
return bindActionCreators({ ...ActionList1, ...ActionList2 }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(PresentationComponent1);
So i have list of actions as specified in my action file which i import and pass it on to my presentational component. Within my presentational component, i trigger these actions based on the user interaction with the screen. For e.g.
onRadioButtonChange(event) {
this.props.changeRadioButtonValue(event.target.value);
}
In this way, there are a bunch of actions which i call from my presentational component. Now, i am using Airbnb's eslint config as base. Now, one of the rules is to validate the props validation, the failing on which it throws the below error :-
changeRadioButtonValue is missing in props validation
Now, what is the recommended way to tackle this?
Write proptypes for each of the actions? Is there a way we can specify the entire action file in the proptypes validation, rather than individual action?
Or disable prop validation in eslint?