DEV Community

Yacine C
Yacine C

Posted on

React - Manage many state updates

Managing multiple states can rapidly become a complex task.

In effect, it can create some synchronous problems. Let’s say you have this component:

const MyComponent = () => {
    const [users, setUsers] = useState<User[]>([]);
    const [loading, setLoading] = useState<boolean>(false);

    const handleClick = () => {
    setLoading(true);

    someMethod()
            .then((newUsers) => {
          setUsers(newUsers);
          setLoading(false);
        });
  };

    return loading ? (<Loader />) : (<button onClick={handleClick}>Update</button>);
};
Enter fullscreen mode Exit fullscreen mode

The code is currently working. However, as it becomes more complex and has more states, you may encounter issues with its values and component refreshing.

To avoid this kind of behavior, you can store all your data in the same object.

const MyComponent = () => {
    const [object, setObject] = useState({
        loading: false,
        users: []
    });

    const handleClick = () => {
    setObject({...object, loading: true});

    someMethod()
            .then((newUsers) => {
          setObject({...object, users: newUsers, loading: false});
        });
  };

    return loading ? (<Loader />) : (<button onClick={handleClick}>Update</button>);
};
Enter fullscreen mode Exit fullscreen mode

In this case, that's totally fine because our object is pretty simple. However, if we have to deal with more states, it's better to use a reducer to externalize the object updates.

const reducer = (state, action) => {
    switch(action.type) {
        case "start":
                return {...state, loading: true}
        case "end":
                return {...state, users: action.newUsers, loading: false}
    }
}

const App = () => {
    const [object, dispatch] = useReducer(reducer, {
        loading: false,
        users: []
    });

    const handleClick = () => {
    dispatch({type: "start"});
    someMethod()
            .then((newUsers) => {
            dispatch({type: "end", newUsers});
        });
  };

    return object.loading ? 
        (<Loader />) : 
        (<div><button onClick={handleClick}>Update</button></div>);

};
Enter fullscreen mode Exit fullscreen mode

Now you can be sure that all your states will be synchronized, and you have total control over them.

Top comments (0)