Manage eslint errors with Redux Actions - reactjs

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?

Related

Store with multiple reducers from different components. React / Redux

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?

Getting a Cannot update during an existing state transition message after library updates

Have a ReactJS + Redux + Saga application that was recently updated to use the latest (or close to latest) versions of the respective JS libraries. After the library updates (no code changes) and running the application, I immediately see the "Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state." warning message in the console. It looks to be triggered by redux when I invoke the dispatch function (which then calls a function in Provider.js, then goes through react-dom, and then in turn writes the warning message. Again nothing in my code has changed, and my code is essentially built using stateless functions.
Not sure how to go about figuring out what is causing this warning-- although the app still runs ok as expected. Using React 16.8.6, react-redux 6.0.1, react-router-dom 5.0.0, redux 4.0.1, redux-saga 1.0.2, and connected-react-router 6.4.0.
Below is a sample page that would cause the warning message:
import React from 'react'
import {connect} from 'react-redux'
import {links} from '../links'
import {notify} from '../notifications'
const Home = props => {
const {dispatch} = props
return (
<main>
<p>
Go to Details...
</p>
</main>
)}
const dispatcher = dispatch => {
dispatch(notify(links.HOME))
return {dispatch}
}
export default connect(null, dispatcher)(Home)
You cannot call to dispatch inside the disaptcher function.
react-redux's connect parameters are:
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
mapDispatchToProps is what you called dispatch. These params are eventually run as functions that called in the render loop of the connected component. When you dispatch in the render loop it changes the state of a React component (looks like it's the Provider), which is forbidden by React.
Solution
Move the dispatch(notify(links.HOME)) to lifecycle method. For example you can add to the Home component (this will require to rewrite the Home component as an extension of React.Component class:
componentDidMount() {
dispatch(notify(links.HOME))
}
UPDATE
If you want to do this with classless component see that question

React redux bindActionCreators usage

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.

Correct way to pass a click handler from Container, which doesn't modify the state?

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)

ES6 React Redux syntax clarification

I'm new to ES6 and Redux. Im looking at some code and trying to understand what is going on in this new ES6 syntax.
I feel like this may be simple but i am not understanding it and it might help someone else in a similar position to me.
i want to know how the following code is creating a react element. im familiar with the React.createClass method, but that doesnt seem to be stated here or at least not explicitly. i can see React is imported, but it isnt mentioned in the rest of the code. so then how the FileTable get turned into a react component?
I can see the const variable FileTable seems to contain what would usually go in the render method of React.createClass, but if that is the case, where would methods like componentDidMount, componentDidUpdate, etc be defined?
Any help on this is greatly appreciated.
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions';
const FileTable = ({ fileList, getFileList}) => {
return (
<ul className="filterable-table">
{fileList.map((file)=><li>{file.fileName}</li>)}
</ul>
);
};
FileTable.propTypes = {
fileList: PropTypes.array,
};
const mapStateToProps = (state) => {
return {
fileList: state.fileList
};
};
const mapDispatchToProps = (dispatch) => {
return {
getFileList: () => dispatch(actions.getFileList())
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(FileTable);
You can create react components in 3 ways - React.createClass, ES6 class or
Stateless (pure) function component. This is a stateless component, which means that it doesn't have state, life cycle methods (like componentDidMount or componentDidUpdate), and refs, and as you surmised it's similar to the render method of a react class.
Whenever you need a purely representational dumb component you can use a stateless component, due to its brevity. It goes nicely with redux, as the connect create a smart component that wraps the stateless method.
Regarding performance, stateless components don't have any performance gain over ES6 class component without state. However, Facebook stated that in the future there will be some optimizations.
It doesn't have to be declared here as a React component; React knows about pure functions.
Pure functions don't need to inherit from Component. They're not appropriate for all component types, but for simple HTML renders they're preferred (e.g., see eslint-plugin-react prefer-stateless-function.
Pure functions don't have component lifecycles, associated methods, etc.

Resources