SkyeBoniwell
SkyeBoniwell

Reputation: 7092

combining useState hook in a react component

I recently started using react hooks a lot.

State management seems more intuitive to me when using "React.useState".

Anyway, while it's working ok, I know it's starting to look cluttered the more values I am starting to save to state.

For example, as my car parts app has progressed, it is now looking like this:

const [isShown, setIsShown] = React.useState(false);
const [idVal, setIdValue] = React.useState(false);
const [partNameVal, setPartNameValue] = React.useState(false);
const [engineEngineEngineTypeVal, setEngineEngineTypeValue] = React.useState(false);
const [displacementVal, setDisplacementValue] = React.useState(false);
const [makeVal, setMakeValue] = React.useState(false);
const [countryVal, setCountryValue] = React.useState(false);

const hide = () => setIsShown(false);

const show = (id, partName, engineEngineType, displacement, department, country) => {
    setIsShown(true);
    setIdValue(id);
    setPartNameValue(partName);
    setEngineTypeValue(engineEngineType);
    setDisplacementValue(displacement);
    setMakeValue(department);
    setCountryValue(country);
}

<p>ID:  {idVal}</p>
<p>PartName:  {partNameVal}</p>
<p>EngineType:  {engineEngineTypeVal}</p>
<p>Displacement:  {displacementVal}</p>
<p>Make:  {makeVal}</p>
<p>Country:  {countryVal}</p>

I was wondering if there's a way to make this more readable, but still be very intuitive.

Thanks!

Upvotes: 2

Views: 2076

Answers (4)

Dennis Vash
Dennis Vash

Reputation: 53874

Typically you want to handle a single object or use useReducer, something like:

const INITIAL_CAR = {
  id: 0,
  part: "4xE3",
  country: "USA",
  // ... More entries
};

const CarApp = () => {
  const [car, setCar] = useState(INITIAL_CAR);
  const [isShown, setIsShown] = useState(false);

  const show = (carProps) => {
    setIsShown(true);
    setCar(carProps);
  };

  const { id, part, engine, displacement, make, county } = car;

  const updateCountry = (country) =>
    setCar((prevCar) => ({ ...prevCar, country }));

  const updateCarProperty = ({ property, value }) =>
    setCar((prevCar) => ({ ...prevCar, [property]: value }));

  return (
    <div>
      {isShown && (
        <>
          <p>ID: {id}</p>
          <p>PartName: {part}</p>
          <p>EngineType: {engine}</p>
          <p>Displacement: {displacement}</p>
          <p>Make: {make}</p>
          <p>Country: {country}</p>{" "}
        </>
      )}
      // use show, updateCountry, updateProperty etc.
    </div>
  );
};

Upvotes: 3

Mahdi N
Mahdi N

Reputation: 2178

You can make a new file to extract all your hook logic from your component.

Call if for example useHooks.js

export default () => {
const [isShown, setIsShown] = React.useState(false);
const [idVal, setIdValue] = React.useState(false);
const [partNameVal, setPartNameValue] = React.useState(false);
const [engineEngineEngineTypeVal, setEngineEngineTypeValue] = React.useState(false);
const [displacementVal, setDisplacementValue] = React.useState(false);
const [makeVal, setMakeValue] = React.useState(false);
const [countryVal, setCountryValue] = React.useState(false);

const hide = () => setIsShown(false);

const show = (id, partName, engineEngineType, displacement, department, country) => {
    setIsShown(true);
    setIdValue(id);
    setPartNameValue(partName);
    setEngineTypeValue(engineEngineType);
    setDisplacementValue(displacement);
    setMakeValue(department);
    setCountryValue(country);
}

return [isShown, idVal, partNameVal, engineEngineEngineTypeVal, displacementVal, 
makeVal, countryVal, show, hide];
}

The idea was here to put all your hooks logic in a function and return values that you need inside your JSX.

And in your component import and use all properties exported from useHooks

import useHooks from './useHooks';

const [isShown, idVal, partNameVal, engineEngineEngineTypeVal, displacementVal, 
makeVal, countryVal, show, hide] = useHooks();

Hope the idea is clear

Upvotes: 1

Trisma
Trisma

Reputation: 765

The way I mostly handle this much of state in a component is using one useState, that way it's just a big object.

Here is a small example :

const [state, setState] = useState({
  num: 1,
  cars: ['volvo', 'mazda'],
  john: {name: 'John', last: 'Foo'}
})

And if you want to change something in that I usually use this function

const onChange = (name, value) => {
  setState(prevState => ({...prevState, [name]: value}))
}

This will change the key name to the value value. This is way clearer in my eyes.

Upvotes: 1

Rost
Rost

Reputation: 72

I'd say that it's the case for useReducer hook.

https://reactjs.org/docs/hooks-reference.html#usereducer

const initialState = {
      isShown: false,
      idVal: 0,
      ....
};

function reducer(state, action) {
  switch (action.type) {
    case 'show':
      return {
        ...state,
        isShown: true,
        idVal: action.payload.idVal
      };
    case 'hide':
      return {
        ...state,
        isShown: false
      }
    ...
    default:
      throw new Error();
  }
}

const [state, dispatch] = useReducer(reducer, initialState);

dispatch({type: 'show', payload: { idVal: 1}})

Upvotes: 3

Related Questions