skip to Main Content

Can anyone explaine me please, just start learn React, I’m confused in one thing in this code:

import { useState } from "react";
import ReactDOM from "react-dom/client";

function Car() {
  const [car, setCar] = useState({
    brand: "Ford",
    model: "Mustang",
    year: "1964",
    color: "red",
  });

  const updateColor = () => {
    setCar((previousState) => {
      return { ...previousState, color: "blue" };
    });
  };

  return (
    <>
      <h1>My {car.brand}</h1>
      <p>
        It is a {car.color} {car.model} from {car.year}.
      </p>
      <button type="button" onClick={updateColor}>
        Blue
      </button>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Car />);

previousState , If we only called setCar({color: "blue"}), this would remove the brand, model, and year from our state,
so previousState concatenating them, but how previousState accessed brand, model and year? ewhen they were attributed to him?

previousState is not a keyword no?

5

Answers


  1. using previousState is just a convention. You could just correctly written the updater like so.

    setCar((p) => {
          return { ...p, color: "blue" };
        });
    
    

    In this case:

    (p) => {
          return { ...p, color: "blue" };
        }
    

    Is just a bog standard javascript callback function. Where we pass an anonymous function as an argument to another function and it is called behind the scenes with a value passed as an argument.

    Login or Signup to reply.
  2.     setCar((previousState) => {
          return { ...previousState, color: "blue" };
        });
    

    We can split this into:
    setCar() and

    (previousState) => { return { ...previousState, color: "blue" }; }
    

    wich is an anonymus function. React call your function and set in the param the old state, so its not a keyword, its just the name you give to the old state.

    Login or Signup to reply.
  3. Let me clear this confusition, when you call setCar((previousState) => { ... }), React internally retrieves the current state object ({ brand: "Ford", model: "Mustang", year: "1964", color: "red" }) and passes it as the previousState argument to the updater function. Inside the updater function, you can access and use the properties of previousState (brand, model, year, color) to compute the new state.
    The spread operator (...previousState) is used to create a new object that includes all the properties of previousState. This ensures that the new state object retains the existing properties (brand, model, year) while allowing you to update the color property.
    So, when you call setCar((previousState) => { return { ...previousState, color: "blue" }; }), the new state object will be { brand: "Ford", model: "Mustang", year: "1964", color: "blue" }.

    Login or Signup to reply.
  4. As stated in the comment, if you pass a function to the updater react treat it as a pure function and the argument is the "current" state of the component. You are confuse by the previousState name but it’s no reserve keyword. It’s just there the make your life easier to understand what it contains.

    Login or Signup to reply.
  5. The callback variant of the state setter function consumes the current state, and produces a new immutable state.

    Here is an explanation:

    const updateColor = () => {
      // State setter callback gets the current value
      setCar((currentCar) => {
        // For a shallow object, this is not needed, but useful for nested objects
        const carCopy = structuredClone(currentCar);
        // Spread the existing car state, with the updated values
        const updatedCar = { ...carCopy, color: "blue" };
        // Return the new (imutable) state
        return updatedCar;
      });
    };
    

    Working snippet

    Here is the React application in action:

    const { Fragment, useState } = React;
    
    function Car() {
      const [car, setCar] = useState({
        brand: "Ford",
        model: "Mustang",
        year: "1964",
        color: "red",
      });
    
      const updateColor = () => {
        setCar((currentCar) => ({
          ...structuredClone(currentCar),
          color: "blue"
        }));
      };
    
      return (
        <Fragment>
          <h1>My {car.brand}</h1>
          <p>
            It is a {car.color} {car.model} from {car.year}.
          </p>
          <button type="button" onClick={updateColor}>
            Blue
          </button>
        </Fragment>
      );
    }
    
    ReactDOM.createRoot(document.getElementById("root")).render(<Car />);
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search