5

Imagine a scenario that there's a same operation through different values (For instance generating a custom html element for different input values); in the case of using a component class, I would mocked this as follow:

const onFuncClicked = property => newVal => {
 this.setState({ [property]: newVal })
}

but what if i use react hooks:

  const onFuncClicked = property => newVal => {
    eval(`set${property}(${newVal})`);
  }

not only using eval is not recommended for thousands of reasons, but this code does not work at all!! It generates the correct useState function but the component does not know it even and gives a ReferenceError that that function (generated useState) is not defined

Elmira Khodaee
  • 93
  • 1
  • 1
  • 11
  • 1
    With `useState` you're free to use an object as the data and when calling the setter you would just update the object as opposed to trying to dynamically figure out which setter to use. See this question here: https://stackoverflow.com/questions/55342406/updating-and-merging-state-object-using-react-usestate-hook – Khauri Aug 10 '19 at 12:29

2 Answers2

4

One way to approach this is to use a map of methods to the property names:

const [property, setProperty] = useState(defaultValue);

const methodMap = { propetryName: setPropertyName, /* ... more fields */ };

Then you can call it from your set method like so:

const onClicked = (property, value) => {
    methodMap[property](value);
}

Another option, and probably more common one, would be to have state as an object with all your properties and change them by prop name:

const [state, setState] = useState({property: value});

const onClicked = (property, value) => {
    setState(state => {...state, [property]: value});
}
Clarity
  • 10,730
  • 2
  • 25
  • 35
  • The fist solution works but painful to write if you have dozens of possible useStates. but the second one does now work i because if want to distinguish the appropriate useState from the property – Elmira Khodaee Aug 10 '19 at 13:05
  • The second option is similar to using `setState` in class based components. – Clarity Aug 10 '19 at 13:06
2

well, if you are already using hooks and useState and did end up with a bunch of them that make your code look too complex I suggest using useReducer, here is a sample from official documentation:


function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}```
Pooria Khodaveissi
  • 395
  • 1
  • 8
  • 16