Passing state to siblings onChange

Viewed 57

I have a component which contains an <input type="range"></input> element. In that component I have a function that changes the state when that slider is moved.

I would like to not only be able to use that state to change the span tag inside the Slider component but also 2 other sibling components which will be rendering that same value.

So as I move that slider I want to see the value change on multiple places on the screen.

Slider.jsx

function Slider() {
  const [value, setValue] = useState(0.50)

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

  return (
    <div className='slider'>
      <div className="label">
        <label htmlFor="value">Value</label>
        <span>{value}</span>
      </div>
      <input onChange={handleChange} type="range" id="value" name="value" min="0.00" max="100.00" step='0.01'></input>
    </div>
  )
}

Component1.jsx

function Component1() {

  return (
    <div>
      <p>{value}</p>
    </div>
  )
}

Component2.jsx

function Component2() {

  return (
    <div>
      <p>{value}</p>
    </div>
  )
}

Here's the structure of my app, as you can see Component1 and Component2 are siblings of Slider.

├── App.js
├── components
│   ├── Slider.jsx
│   ├── Component1.jsx
│   └── Component2.jsx
3 Answers

There is React hook that is specifically made for this situation, useContext. Look into it here.

I also found this tutorial to be very helpful on this topic.

You can store value state in a parent component that hosts Slider, Component1, Component2 . For example, I use App Component:

export default function App() {
  const [value, setValue] = useState(0.5);

Then, define a function to set value:

const onValueChange = (val) => {
    setValue(val);
  };

Pass onValueChange to Slider props:

<Slider onValueChange={(val) => onValueChange(val)} />

Whenever there is a change in slider value, you can invoke:

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

Value changed will be reflected in Component 1 and 2:

      <Component1 value={value} />
      <Component2 value={value} />

See my working sample: https://codesandbox.io/s/silent-voice-jjqpw?file=/src/App.js:406-476

Sibling components should be rendered in the same component to be considered siblings.

for example, let's suppose that we have a component called ParentComponent.js I am assuming that Component2 and Component1 take property called value, and Slider take property called value and callback function called onSlide which will be called inside Slider component whenever the input value changes and passes the value to it.

// ParentComponent.js
import React from "react";
import Component2 from "path/to/Component2";
import Component1 from "path/to/Component1";
import Slider from "path/to/Slider";

export default function ParentComponent(props) {
  const [value, setValue] = useState(0.50)

  return (
    <div>
      <Slider value={value} onSlide={(value) => setValue(value)}/>
      <Component1 value={value} />
      <Component2 value={value} />
    </div>
  )
}

This way your 3 components will be connected with each other within the component that renders them.

Related