How to communicate between sibling components in React

How to transfer props from one sibling to another, please?

In main app I have only 2 siblings:

Input:

import React from "react";

const Input = () => {
  return (
    <>
      <label htmlFor="name">Full Name</label>
      <input type="text" id="name" placeholder="TheDareback" />
      <label htmlFor="job">Job Title</label>
      <input type="text" id="job" placeholder="Frontend Developer" />
    </>
  );
};

export default inputDetails;

Preview:

import React from "react";

const Preview = () => {
  return (
    <>
      <table>
        <thead>
          <tr>
            <th>{/* here I need a Full Name from the input */}</th>
            <th>{/* here I need a Job Title from the input*/}</th>
          </tr>
        </thead>
      </table>
    </>
  );
};

export default Preview;

I tried to add useEffect to Preview to read the value of each input.

for example

  const name = document.querySelector("#name");
  const [inputName, setInputName] = useState("TheDareback");

  useEffect(() => (name.value ? setInputName(name.value) : null));

But I’m still getting an error:

Preview.js:9 Uncaught TypeError: Cannot read properties of null (reading 'value')

Is it possible to run useEffect only during the second rendering? Alternatively, is there another option than to move the props directly from Input.js where would I create a handler for each onChange in input?

Thank you very much for heading in the right direction.

>Solution :

Keep the state in the App component and give setter to Input and state to Preview component.

App.js

import Input from "./Input";
import Preview from "./Preview";

export default function App() {
  const [state, setState] = useState({ name: "", job: "" });
  return (
    <div className="App">
      <Input setState={setState} />
      <Preview state={state} />
    </div>
  );
}

Input.js

import React from "react";

const Input = ({ setState }) => {
  const onChangeHandler = (e) => {
    setState((prevState) => ({
      ...prevState,
      [e.target.id]: e.target.value
    }));
  };

  return (
    <>
      <label htmlFor="name">Full Name</label>
      <input
        type="text"
        id="name"
        placeholder="TheDareback"
        onChange={onChangeHandler}
      />
      <label htmlFor="job">Job Title</label>
      <input
        type="text"
        id="job"
        placeholder="Frontend Developer"
        onChange={onChangeHandler}
      />
    </>
  );
};

export default Input;

Preview.js

import React from "react";

const Preview = ({ state: { name, job } }) => {
  return (
    <>
      <table>
        <thead>
          <tr>
            <th>{name}</th>
            <th>{job}</th>
          </tr>
        </thead>
      </table>
    </>
  );
};

export default Preview;

Code Sandbox

Leave a Reply