18

I want to pass a variable username from sibling1 component to sibling2 component and display it there.

Sibling1 component:

const sibling1 = ({ usernameData }) => {
   // I want to pass the username value I get from input to sibling2 component
  const [username, setUsername] = useState(""); 

  const handleChange = event => {
    setUsername(event.target.value);
  };

  return (
    <Form.Input
        icon='user'
        iconPosition='left'
        label='Username'
        onChange={handleChange}
      />
    <Button content='Login' onClick={handleClick} />
  )
}

export default sibling1;

Sibling2 component:

export default function sibling2() {
  return (
    <h1> Here is where i want to display it </h1>
  )
}
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
gospecomid12
  • 712
  • 3
  • 11
  • 25
  • Is sibling2 called from sibling1? If so, you can just pass props. Or else you need to store in-app state and get from there. – Byrisetti Hemanth May 16 '20 at 12:14
  • @QuentinGrisel we don't know if he was downvoter ;) (btw wasn't me) I suspect some answerers do serial downvoting sometimes if they get a downvote which ain't healthy – Giorgi Moniava May 16 '20 at 12:29
  • @giorgim That's right, i thought about it after. But the advide is still valid. And i meant nothing bad by saying that, it's just unproductive – Quentin Grisel May 16 '20 at 12:31

3 Answers3

35

You will need to handle your userName in the parent of your siblings. then you can just pass setUsername to your sibling1, and userName to your sibling2. When sibling1 use setUsername, it will update your parent state and re-render your sibling2 (Because the prop is edited).

Here what it looks like :

const App = () => {
  const [username, setUsername] = useState('Default username');
  return (
    <>
      <Sibling1 setUsername={setUsername} />
      <Sibling2 username={username} />
    </>
  )
}

const Sibling2 = ({username}) => {
  return <h1> Helo {username}</h1>;
}

const Sibling1 = ({setUsername}) => {
  return <button onClick={setUsername}>Set username</button>;
}
Quentin Grisel
  • 4,794
  • 1
  • 10
  • 15
  • 6
    THIS!! Best explanaiton to such a "hard" problem for me. Thank you:) – gospecomid12 May 16 '20 at 14:35
  • 4
    You're welcome ;) remember that component based language are like trees, so if leaves need something, it's provided by the trunk most of the time ;) – Quentin Grisel May 16 '20 at 14:53
  • I'm getting this warning: `Warning: Cannot update a component (`TagsListPage`) while rendering a different component (`TagsListTableBody`). To locate the bad setState() call inside `TagsListTableBody`, follow the stack trace as described`... It seems better to go with Context solution from @tswistak – Kostanos Apr 15 '22 at 20:57
  • @Kostanos Without any code it's impossible to help you. Your problem might come from your own code so I can only advice you to open a new question if you don't find a solution. Using a context is a solution especially when you have to share data across multiple level of your tree. – Quentin Grisel Apr 16 '22 at 21:18
  • The code in this answer will trigger the re-render of entire parent with its children. I'm looking for solution which will not trigger the full re-render, but only those siblings who involved on it – Kostanos Apr 26 '22 at 21:09
14

In parent of these two components create a context where you will store a value and value setter (the best would be from useState). So, it will look like this:

export const Context = React.createContext({ value: null, setValue: () => {} });

export const ParentComponent = () => {
 const [value, setValue] = useState(null);

 return (
  <Context.Provider value={{value, setValue}}>
   <Sibling1 />
   <Sibling2 />
  </Context.Provider>
 );

Then in siblings you are using it like this:

const Sibling1 = () => {
 const {setValue} = useContext(Context);

 const handleChange = event => {
  setValue(event.target.value);
 };
 // rest of code here
}

const Sibling2 = () => {
 const {value} = useContext(Context);

 return <h1>{value}</h1>;
}
tswistak
  • 487
  • 5
  • 9
  • 2
    I think this is the best answer, if you want to avoid the parent to be re-rendered each time value is changed – Kostanos Apr 26 '22 at 21:11
3

best way: React Context + hooks

you can use React Context. take a look at this example:

https://codesandbox.io/s/react-context-api-example-0ghhy

Hamid Sarani
  • 755
  • 1
  • 5
  • 15