React Hooks cheat sheet
Tags: engineeringmonday, javascript, react, tutorial
Published: 2020-03-02 09:20:12

Not so long ago I started working with functional components instead of class based ones. The main goal was to learn how to implement React Hooks inside them. This way we can write less code and make it more reusable. 

The benefits of using hooks and functional components are reusability, simpler & shorter code and the simplicity of testing those components.

The usual class approach of things is now a thing of the past. And here I will share short and understandable react hooks cheat sheet. This is not a tutorial for hooks as there are many articles online and the docs are [really good](https://reactjs.org/docs/hooks-intro.html). This serves as a quick reference for people already somewhat familiar with writing hooks. If you are new to hooks, you can still take a look. With that said, let's begin. 
 
**UseState - similar to React state and setState**

- with primitive value

```javascript
const App = () => {
    const [carSpeed, updateCarSpeed] = useState(10);
    return (
        <div>
            <p>Car is going {carSpeed} km/h</p>
            <button onClick={() => updateCarSpeed(carSpeed + 5)}>
                Speed up
            </button>
        </div>
    );
};
```

- with object

```javascript
export const App = () => {
    const [carForm, updateForm] = useState({});
    const updateField = (e) => {
        updateForm({ ...carForm, [e.target.name]: e.target.value });
    };

    const handleSubmit = (e) => {
        e.preventDefault();
        console.log(carForm);
    };
    return (
        <form onSubmit={handleSubmit}>
            <label>
                Car Owner:
                <input
                    value={carForm.owner}
                    name="owner"
                    onChange={updateField}
                />
            </label>
            <br />
            <label>
                Car model:
                <input
                    value={carForm.model}
                    name="model"
                    onChange={updateField}
                />
            </label>
            <button>Submit</button>
        </form>
    );
};
```

**UseEffect - similar to componentDidUpdate**

- only triggers once (because of empty array param)

```javascript
export const App = () => {
    const [carsData, updateCars] = useState({});

    useEffect(() => {
        fetch("http://example.com/cars.json")
            .then((resp) => resp.json())
            .then((data) => {
                updateCars(data);
            });
    }, []);

    const renderCars = () => {
        return carsData.cars.map((car) => {
            <p key={car.id}>{car.name}</p>;
        });
    };

    return <div>{renderCars()}</div>;
};
```

- trigger on carName variable change

```javascript
export const App = () => {
    const [carName, updateCarName] = useState("");

    useEffect(() => {
        console.log("changed");
    }, [carName]);

    return (
        <div>
            <input
                value={carName}
                onChange={(e) => updateCarName(e.target.value)}
            />
        </div>
    );
};
```

**UseReducer with React.memo HOC and useCallback**
- This example makes use of [useReducer](https://reactjs.org/docs/hooks-reference.html#usereducer) hook which acts similar to Redux. It has a reducer and actions that change the state in the reducer. We also make use of the [React.memo](https://reactjs.org/docs/react-api.html#reactmemo) and useCallback for the sole reason of not re-rendering new "Car" components when each car is checked that it is sold.
- [UseCallback](https://reactjs.org/docs/hooks-reference.html#usecallback) - this hook is used when you have a component with a frequently re-rendering child and to which you pass a callback to. Without it the addCar function would be re-instantiated each time a new car is added to the list.


```javascript

// initial cars state
const initialState = [
  {
    id: id(),
    name: "Audi A4",
    description: 'Black tint with red wheels, 100kw',
    sold: false
  },
  {
    id: id(),
    name: "Porsche 911",
    description: 'Cherry red tint with dark golden wheels, 300kw',
    sold: false
  },
  {
    id: id(),
    name: "Lamborghini Gallardo",
    description: 'Lamborghini green with black wheels, 500kw',
    sold: false
  },
];


// action names
const CAR_ADD = 'CAR_ADD';
const CAR_SELL = 'CAR_SELL';

// the reducer
const reducer = (state, action) => {
  if (action.type === CAR_ADD) {
    return [action.payload, ...state];
  }

  if (action.type === CAR_SELL) {
    return state.map(car => {
      if (car.id !== action.payload.id) {
        return car;
      }
      return { ...car, sold: !car.sold };
    });
  }

  return state;
};

const App = () => {
  const [cars, dispatch] = useReducer(reducer, initialState);

  const addCar = useCallback(({ name, description }) => {
    dispatch(
      {
        type: CAR_ADD,
        payload: {
          name,
          description,
          sold: false,
          id: id()
        }
      },
      [dispatch]
    );
  });

  const toggleSold = useCallback(
    id => {
      dispatch({
        type: CAR_SELL,
        payload: {
          id
        }
      });
    },
    [dispatch]
  );

  return (
    <div style={{ maxWidth: 400, margin: '0 auto' }}>
      <NewCarForm onSubmit={addCar} />
      <Cars cars={cars} onSell={toggleSold} />
    </div>
  );
};

const Cars = ({ cars = [], onSell }) => {
  return (
    <div>
      <h2>Cars ({cars.length})</h2>
      {cars.map(car => (
        <Car key={car.id} car={car} onSell={onSell} />
      ))}
    </div>
  );
};

const Car = React.memo(({ car, onSell }) => {
  return (
    <div style={{border:"1px solid", margin: 10, padding: 10}}>
      <h3>{car.name}</h3>
      <p>{car.description}</p>
      <div>
        <label>
          <input
            type="checkbox"
            checked={car.sold}
            onChange={() => onSell(car.id)}
          />
          Sold
        </label>
      </div>
    </div>
  );
});

const NewCarForm = React.memo(({ onSubmit }) => {
  const [name, setCarName] = useState('');
  const [description, setCarDescription] = useState('');

  const handleChange = e => {
    e.preventDefault();
    onSubmit({ name, description });
  };

  return (
    <form onSubmit={handleChange}>
      <input
        placeholder="Car name"
        type="text"
        value={name}
        onChange={event => setCarName(event.target.value)}
      />
      <input
        placeholder="Car description"
        type="text"
        value={description}
        onChange={event => setCarDescription(event.target.value)}
      />
      <input type="submit" />
    </form>
  );
});
```

That would be all, thank you for reading kind stranger. Do you have something of your own to add to the list? Let me know.