Henrique
Henrique

Reputation: 133

How can I get all states of children from parent element?

How can I get all states of children from parent element?

I created a page, and there are a few elements, the most important is this component list.

Here is the parent element:

const Home = () => {
    const walls = [1, 2, 3, 4];

    return (
        <Layout>
                {walls.map(wall => {
                    return <Wall key={wall} index={wall} />;
                })}
        </Layout>
    );
};

As you can see, it generates a list of elements with map.

So, how can I get all children states from parent element?

This is the child component:

const Wall = ({ index }: IWall) => {
    const { doors, windows, handleWindows, handleDoors } = 
    useWall();

    return (
        <div>
            <input .../>
            <input .../>
            ...
        </div>
    );
};

And it's hooks:

export const useWall = () => {
    const [doors, setDoors] = useState(0);
    const [windows, setWindows] = useState(0);

    const handleWindows = (value: number) => {
        if (value < 0 || value > 50) return;

        setWindows(value);
    };

    const handleDoors = (value: number) => {
        if (value < 0 || value > 50) return;

        setDoors(value);
    };


    return { doors, windows, handleWindows, handleDoors };
};

Upvotes: 2

Views: 558

Answers (1)

Drew Reese
Drew Reese

Reputation: 203466

It's generally considered a React anti-pattern for parent components to reach into children components to access state and functions. The solution is to Lift State Up to the parent component and pass the state and state update callbacks as props down to children components.

Example:

const Home = () => {
  const [walls, setWalls] = useState<IWall[]>(
    [1, 2, 3, 4].map((id) => ({
      id,
      doors: 0,
      windows: 0
    }))
  );

  const changeHandler = (id: number) => (
    e: React.ChangeEvent<HTMLInputElement>
  ) => {
    const { name, value } = e.target;

    if (Number(value) >= 0 && Number(value) <= 50) {
      setWalls((walls) =>
        walls.map((wall) =>
          wall.id === id ? { ...wall, [name]: value } : wall
        )
      );
    }
  };

  return (
    <Layout>
      {walls.map((wall) => {
        return (
          <Wall
            key={wall.id}
            wall={wall}
            changeHandler={changeHandler(wall.id)}
          />
        );
      })}
    </Layout>
  );
};

...

interface IWall {
  id: number;
  doors: number;
  windows: number;
}

interface WallProps {
  wall: IWall;
  changeHandler: React.ChangeEventHandler<HTMLInputElement>;
}

const Wall = ({ changeHandler, wall }: WallProps) => {
  return (
    <div>
      <h2>Wall: {wall.id}</h2>
      <label>
        Doors
        <input
          name="doors"
          type="number"
          value={wall.doors}
          onChange={changeHandler}
        />
      </label>
      <label>
        Windows
        <input
          name="windows"
          type="number"
          value={wall.windows}
          onChange={changeHandler}
        />
      </label>
    </div>
  );
};

Edit adoring-khayyam-3sd3udhow-can-i-get-all-states-of-children-from-parent-element

enter image description here

Upvotes: 2

Related Questions