How do you destructure a React useState hook into a namespace?

Tags: ,



As a personal preference I wrap React props in namespaces. It helps me organize where different props come from.

With the useState hook I’m doing this.

function MyComponent() {
  const [todoCount, setTodoCount] = useState(100);
  const [doneCount, setDoneCount] = useState(0);
  const myState = {
    todoCount,
    setTodoCount,
    doneCount,
    setDoneCount
  };

  return (
    <>
      <Text>Todo {myState.todoCount}</Text>
      <Text>Done {myState.doneCount}</Text>
    </>
  );
}

Is there a more succinct syntax for state setup?

My failed attempt was

const myState = {
  [todoCount, setTodoCount]: useState(100),
  [doneCount, setDoneCount]: useState(0);
};

Answer

Sounds like the type of thing you could do as part of a custom hook e.g.

 function useMappedState(defaultState = {}) {
   const keys = Object.keys(defaultState);
   return keys.reduce((map, k) => {
     const fk = `set${k.charAt(0).toUpperCase()}${k.slice(1)}`;
     const [state, setState] = useState(defaultState[k]);
     map[k] = state;
     map[fk] = setState;
     return map;
   }, {});
 }
 ...
 const state = useMappedState({
   todoCount: 100,
   doneCount: 0
 });
 console.log(state.todoCount) // 100
 state.setTodoCount(5); // should set state of todoCount

In theory, this should give you what you want, but I’ve not tested so use with caution (e.g. I’m not even sure if hooks can be called can be called inside an iterator). – this works fine.

Although, what you are doing is really similar to what useReducer already does, might be worth some experimenting with that hook instead.



Source: stackoverflow