javascriptreactjsreduxreact-reduxredux-logger

React mapStateToProps state calling reducers infinitely


const mapDispatchToProps = dispatch => ({
  getUsers: (payload) => dispatch({ type: "USERS", payload: payload })
});

const mapStateToProps= state => ({
  ctr: state.TestReducer,
  users: state.Users
})  

const Dashboard = (props) => { 
  axios.get("https://jsonplaceholder.typicode.com/users")
    .then(function(response) {
      props.getUsers(response.data);
    });

  return (
    <h1>hello dashboard</h1>
  )
}

export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);

When I add the Users reducer in mapStateToProps, in browser console reducers from redux logger are executing infinitely as shown here enter image description here

I want to store the Users that I get from axios to the User reducer. And those users I want to access using state in mapStateToProps so that I can use as props users. But the problem is redux logger infinitely logs state in my web browser console as shown in the image.

How to stop this?

I tried many ways but did not find a proper solution.


Solution

  • The issue is that the Dashboard component is issuing the Axios request as an unintentional side-effect. Each time the data is fetch and getUsers action is dispatch this triggers another component render, and triggers again the data fetch and action dispatch... repeat ad nauseam.

    Move the data fetching into a useEffect hook to be initiated as an intentional side-effect.

    const Dashboard = (props) => {
      useEffect(() => {
        axios.get("https://jsonplaceholder.typicode.com/users")
          .then(function(response) {
            props.getUsers(response.data);
          });
      }, []);
    
      ...
    }
    

    Also, FWIW, modern Redux no longer recommends using the connect Higher Order Component, instead you should use the useDispatch and useSelector hooks to dispatch actions and subscribe to the store.

    Example:

    import { useDispatch, useSelector } from 'react-redux';
    
    const Dashboard = () => {
      const dispatch = useDispatch();
    
      const ctr = useSelector(state => state.TestReducer);
      const users = useSelector(state => state.Users);
    
      useEffect(() => {
        axios.get("https://jsonplaceholder.typicode.com/users")
          .then(function(response) {
            dispatch({ type: "USERS", payload: response.data });
          });
      }, []);
    
      ...
    };
    
    export default Dashboard;