Think this question is best answered by the docs:

If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use refs to "make things happen" – instead, the data flow will usually accomplish your goal.

Not sure exactly what you are trying to do, but my hunch is a parent component and passing props is what you really want here.

Answer from Mark McKelvy on Stack Overflow
Top answer
1 of 4
8

Think this question is best answered by the docs:

If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use refs to "make things happen" – instead, the data flow will usually accomplish your goal.

Not sure exactly what you are trying to do, but my hunch is a parent component and passing props is what you really want here.

2 of 4
2

I completely agree with the quote Mark McKelvy has provided. What you are trying to achieve is considered an anti-pattern in React.

I'll add that creating a parent component doesn't necessarily means it has to be a direct parent, you can create a parent component further up the chain, in which you can render an array of all your children components together, having the logic to coordinate between all the children (or pairs of children according to your example) sit inside your parent.

I created a rough example of the concept which should do the trick:

class A extends React.Component {
    onClick(key) {
        alert(this.refs[key].refs.main.innerText);
    }

    render() {
        var children = [];
        for (var i = 0; i < 5; i++)
            children.push.apply(children, this.renderPair(i));

        return (
            <div>
                {children}
            </div>
        );
    }

    renderPair(key) {
        return [
            <B ref={'B' + key} key={'B' + key} onClick={this.onClick.bind(this, 'C' + key)}/>,
            <C ref={'C' + key} key={'C' + key} onClick={this.onClick.bind(this, 'B' + key)}/>
        ];
    }
}

class B extends React.Component {
    render() {
        return <p ref="main" onClick={this.props.onClick}>B</p>;
    }
}

class C extends React.Component {
    render() {
        return <p ref="main" onClick={this.props.onClick}>C</p>;
    }
}


React.render(<A/>, document.getElementById('container'));

And any state you need to save for all your children, you do in the common parent. I really hope this helps.

🌐
Reddit
reddit.com › r/reactjs › access ref method in sibling component
r/reactjs on Reddit: Access ref method in sibling component
October 1, 2021 -

Hi everybody. I'm trying to figure out what is the correct way of accessing a ref method of a child component in a sibling of that child

< Parent>

Const childRef = useRef()

Return ( <> <Child1 sibRef={ref}/> <Child2 ref={childRef}/> </> )

</Parent>

So the problem is ref will be undefined in child1, and cannot use an effect with ref as dependency because ref won't trigger it. Also tried setting the ref in child2 with usecallback, didn't work either

So what's the correct way of access a sibling method through ref? Thanks in advance!

Discussions

React.js - Communicating between sibling components
I'm new to React, and I'd like to ask a strategy question about how best to accomplish a task where data must be communicated between sibling components. ... Say I have multiple components that are children of a single parent that passes down the select boxes dynamically, composed ... More on stackoverflow.com
🌐 stackoverflow.com
Pass state between sibling components in React
In React, state goes top to bottom. A nested component can update the state of a parent if a function defined in the parent has been passed to it as prop. Hence, what you wanna do is not possible (exchanging state between List and Form, two sibling components). More on stackoverflow.com
🌐 stackoverflow.com
Passing data between two sibling React.js components
I have two instances of a component (a search field) on a page, with a second component (a button that makes server calls) between them, as such: ReactDOM.render( More on stackoverflow.com
🌐 stackoverflow.com
ReactJS - Pass references between siblings
The following code helps me to ... two siblings. The setup is done in their parent during render() and componentDidMount() calls. It is based on https://reactjs.org/docs/refs-and-the-dom.html · class App extends React.Component { private _navigationPanel: NavigationPanel; private _mapPanel: MapPanel; constructor() { super(); this.state = {}; } // `componentDidMount()` is called by ReactJS after `render()` componentDidMount() { // Pass _mapPanel to _navigationPanel ... More on stackoverflow.com
🌐 stackoverflow.com
May 3, 2017
🌐
DEV Community
dev.to › andydziabo › how-to-pass-data-between-sibling-components-in-react-2cjg
How to pass data between sibling components in React - DEV Community
February 2, 2023 - Here is what it looks like added to the Search compenent: With the search query data now in the App component, we can simply pass that data down to the Container component as a prop. We have successfully passed data from sibling to sibling using the parent as a go between.
Top answer
1 of 2
45

TLDR: Yes, you should use a props-from-top-to-bottom and change-handlers-from-bottom-to-top approach. But this can get unwieldy in a larger application, so you can use design patterns like Flux or Redux to reduce your complexity.

Simple React approach

React components receive their "inputs" as props; and they communicate their "output" by calling functions that were passed to them as props. A canonical example:

<input value={value} onChange={changeHandler}>

You pass the initial value in one prop; and a change handler in another prop.

Who can pass values and change handlers to a component? Only their parent. (Well, there is an exception: you can use the context to share information between components, but that's a more advanced concept, and will be leveraged in the next example.)

So, in any case, it's the parent component of your selects that should manage the input for your selects. Here is an example:

class Example extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            // keep track of what is selected in each select
            selected: [ null, null, null ] 
        };
    }

    changeValue(index, value) {
        // update selected option
        this.setState({ selected: this.state.selected.map((v, i) => i === index ? value : v)})
    }

    getOptionList(index) {
        // return a list of options, with anything selected in the other controls disabled
        return this.props.options.map(({value, label}) => {
            const selectedIndex = this.state.selected.indexOf(value);
            const disabled = selectedIndex >= 0 && selectedIndex !== index;
            return {value, label, disabled};
        });
    }

    render() {
        return (<div>
            <Select value={this.state.selected[0]} options={this.getOptionList(0)} onChange={v => this.changeValue(0, v)} />
            <Select value={this.state.selected[1]} options={this.getOptionList(1)} onChange={v => this.changeValue(1, v)} />
            <Select value={this.state.selected[2]} options={this.getOptionList(2)} onChange={v => this.changeValue(2, v)} />
        </div>)
    }

}

Redux

The main drawback of the above approach is that you have to pass a lot of information from the top to the bottom; as your application grows, this becomes difficult to manage. React-Redux leverages React's context feature to enable child components to access your Store directly, thus simplifying your architecture.

Example (just some key pieces of your redux application - see the react-redux documentation how to wire these together, e.g. createStore, Provider...):

// reducer.js

// Your Store is made of two reducers:
// 'dropdowns' manages the current state of your three dropdown;
// 'options' manages the list of available options.

const dropdowns = (state = [null, null, null], action = {}) => {
    switch (action.type) {
        case 'CHANGE_DROPDOWN_VALUE':
            return state.map((v, i) => i === action.index ? action.value : v);
        default:
            return state;
    }
};

const options = (state = [], action = {}) => {
    // reducer code for option list omitted for sake of simplicity
};

// actionCreators.js

export const changeDropdownValue = (index, value) => ({
    type: 'CHANGE_DROPDOWN_VALUE',
    index,
    value
});

// helpers.js

export const selectOptionsForDropdown = (state, index) => {
    return state.options.map(({value, label}) => {
        const selectedIndex = state.dropdowns.indexOf(value);
        const disabled = selectedIndex >= 0 && selectedIndex !== index;
        return {value, label, disabled};
    });    
};

// components.js

import React from 'react';
import { connect } from 'react-redux';
import { changeDropdownValue } from './actionCreators';
import { selectOptionsForDropdown } from './helpers';
import { Select } from './myOtherComponents';

const mapStateToProps = (state, ownProps) => ({
    value: state.dropdowns[ownProps.index],
    options: selectOptionsForDropdown(state, ownProps.index)
}};

const mapDispatchToProps = (dispatch, ownProps) => ({
    onChange: value => dispatch(changeDropdownValue(ownProps.index, value));
});

const ConnectedSelect = connect(mapStateToProps, mapDispatchToProps)(Select);

export const Example = () => (
    <div>
        <ConnectedSelect index={0} />
        <ConnectedSelect index={1} />
        <ConnectedSelect index={2} />
    </div>
);

As you can see, the logic in the Redux example is the same as the vanilla React code. But it is not contained in the parent component, but in reducers and helper functions (selectors). An instead of top-down passing of props, React-Redux connects each individual component to the state, resulting in a simpler, more modular, easier-to-maintain code.

2 of 2
7

The following help me to setup communication between two siblings. The setup is done in their parent during render() and componentDidMount() calls.

class App extends React.Component<IAppProps, IAppState> {
    private _navigationPanel: NavigationPanel;
    private _mapPanel: MapPanel;

    constructor() {
        super();
        this.state = {};
    }

    // `componentDidMount()` is called by ReactJS after `render()`
    componentDidMount() {
        // Pass _mapPanel to _navigationPanel
        // It will allow _navigationPanel to call _mapPanel directly
        this._navigationPanel.setMapPanel(this._mapPanel);
    }

    render() {
        return (
            <div id="appDiv" style={divStyle}>
                // `ref=` helps to get reference to a child during rendering
                <NavigationPanel ref={(child) => { this._navigationPanel = child; }} />
                <MapPanel ref={(child) => { this._mapPanel = child; }} />
            </div>
        );
    }
}
🌐
YouTube
youtube.com › watch
React passing data between siblings - YouTube
In this tutorial, you will learn how to pass data between siblings components without using any third-party library.In React you can pass state as props to t...
Published   October 22, 2020
Top answer
1 of 3
5

In React, state goes top to bottom. A nested component can update the state of a parent if a function defined in the parent has been passed to it as prop. Hence, what you wanna do is not possible (exchanging state between List and Form, two sibling components).

For this to work, you should have the state for the list in a parent component, App.js for example, this way:

import Form from "./Components/Form";
import List from "./Components/List";
import {useState} from "react";


function App() {
  const [list, setList] = useState([])
  return (

      <div className="App">
          <header>
              <h1>Shopping List</h1>
          </header>
          <Form list = {list} setList = {setList}/>
          <List list = {list} />
      </div>
  )
}
import React, {useState} from "react";

const List = ({list}) =>{

    return(
        <div>
            <ul>{list.map(item => <li>"test"</li>)}</ul>
        </div>
    )
}

export default List
const Form = ({list, setList}) => {
    const [inputText,setInputText] = useState("")

    const submitBtn = (e) =>{
         e.preventDefault()  
        setList([
            ...list,{inputText}
        ])
    }

    return (
        <form>
            <input
                value={inputText}
                type="text"
                onChange={
                    (e) => setInputText(e.target.value)
                }
            />
            <button type="submit" onClick={submitBtn}>
                <i>Add</i>
            </button>
        </form>
    )
}

export default Form
2 of 3
1

You can't really do what you're asking as React only allows child components to accept state from parent components, it is a top-down process. I would recommend using a React "Context"; A context will allow you to have one component that can share state throughout the entire component tree without having to pass props down through child components. It's basically a store for the whole react app, that can be pulled wherever and whenever needed.

https://reactjs.org/docs/context.html

🌐
Medium
mujeebkhan1831.medium.com › how-to-pass-data-or-state-between-sibling-components-in-react-using-props-cad6bd58e18b
How to pass data or state between sibling components in React using Props | by Mujeeb ur rahman khan | Medium
October 21, 2023 - Now we have updated value in UnitGame parent component, we can simply pass that data down to the DesktopSection child 2 component as a prop · import DesktopSection from "../components/DesktopSection"; import DesktopCodeSection from "../components/DesktopCodeSection"; import React from "react"; const UnitGame = () => { const [height, setHeight] = React.useState("20%"); const [width, setWidth] = React.useState("30%"); return ( <div className="flex w-screen h-screen bg-unitBg"> {/*we will send newHeight and newWidth to child 1 as a prop*/} <DesktopCodeSection onHeightChange={setHeight} onWidthChange={setWidth}/> {/*pass the updated value in child 2*/} <DesktopSection newHeight={height} newWidth={width}/> </div> ); } export default UnitGame;
Top answer
1 of 2
19

I created a jsfiddle with an example of how to share a variable between two components using a parent component.

class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {shared_var: "init"};
    }

    updateShared(shared_value) {
        this.setState({shared_var: shared_value});
    }

    render() {
        return (
            <div>
                <CardSearch shared_var={this.state.shared_var} updateShared={this.updateShared} />
                <RunOnServer shared_var={this.state.shared_var} updateShared={this.updateShared} />
                <div> The shared value is {this.state.shared_var} </div>
            </div>
        );
    }
}

class CardSearch extends React.Component {
    updateShared() {
        this.props.updateShared('card');
    }

    render() {
        return (
            <button onClick={this.updateShared} style={this.props.shared_var == 'card' ? {backgroundColor: "green"} : null} >
            card
            </button>
        );
    }
}

class RunOnServer extends React.Component {
    updateShared() {
        this.props.updateShared('run');
    }

    render() {
        return (
            <button onClick={this.updateShared} style={this.props.shared_var == 'run' ? {backgroundColor: "green"} : null}>
            run
            </button>
        );
    }
}


ReactDOM.render(
  <Parent/>,
  document.getElementById('container')
);
2 of 2
13

As of 2020, Feb; Context API is the way to handle this:

// First you need to create the TodoContext


// Todo.jsx
//...
export default () => {
  return(
    <>
      <TodoContextProvider>
        <TodoList />
        <TodoCalendar />
      </TodoContextProvider>
    </>
  )
}

// Now in your TodoList.jsx and TodoCalendar.jsx; you can access the TodoContext with:
//...
const todoContext = React.useContext(TodoContext);
console.log(todoContext)
//...
//...

Check this video tutorial by The Net Ninja for Hooks & Context API

Good Luck...

Find elsewhere
🌐
YouTube
youtube.com › watch
How to pass data between sibling components in React | Lifting up state | Easiest way - YouTube
Here are the steps we will follow to pass data between sibling components in React.1️⃣ Step 1: Store the state in a parent component through which the data c...
Published   November 26, 2022
🌐
Stack Overflow
stackoverflow.com › questions › 43754617 › reactjs-pass-references-between-siblings
ReactJS - Pass references between siblings
May 3, 2017 - The following code helps me to setup communication between two siblings. The setup is done in their parent during render() and componentDidMount() calls. It is based on https://reactjs.org/docs/refs-and-the-dom.html · class App extends React.Component<IAppProps, IAppState> { private _navigationPanel: NavigationPanel; private _mapPanel: MapPanel; constructor() { super(); this.state = {}; } // `componentDidMount()` is called by ReactJS after `render()` componentDidMount() { // Pass _mapPanel to _navigationPanel // It will allow _navigationPanel to call _mapPanel directly this._navigationPanel.setMapPanel(this._mapPanel); } render() { return ( <div id="appDiv" style={divStyle}> // `ref=` helps to get reference to a child during rendering <NavigationPanel ref={(child) => { this._navigationPanel = child; }} /> <MapPanel ref={(child) => { this._mapPanel = child; }} /> </div> ); } }
🌐
Reddit
reddit.com › r/reactjs › communicating between sibling components.
r/reactjs on Reddit: Communicating between Sibling components.
July 9, 2016 -

I know that one could use something such as Flux/Redux/MobX for this, but how would one communicate between sibling components using the React's suggestion? https://facebook.github.io/react/tips/communicate-between-components.html: says "Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event." However, I am having a hard time conceptualizing what that might look like. For example, if I wanted to build a simple counter app that could display the count within the Display component and increment in the Counter component. How could I do that if there was no parent/child relationship between the two components? In Vue I could create a global event bus to handle such communication. Is this possible in React?

🌐
Stack Overflow
stackoverflow.com › questions › 74211590 › react-pass-ref-to-sibling-component-function-component
React: pass ref to sibling component Function component
You can't directly pass anything between siblings. You can, however, control the state in the parent component or a parent context and, from there, send the data down as props to the component that requires them.
🌐
GitHub
github.com › reduxjs › react-redux › issues › 610
What are the best ways to acheive siblings component communication using react-redux · Issue #610 · reduxjs/react-redux
January 27, 2017 - What are the best ways to acheive siblings component communication using react-redux?? No one assigned · No labels · No labels · No type · No projects · No milestone · None yet · No branches or pull requests ·
Author   iiitmahesh
🌐
Medium
medium.com › @ruthmpardee › passing-data-between-react-components-103ad82ebd17
Passing Data Between React Components | by Ruth M. Pardee | Medium
May 29, 2017 - Set this incoming parameter as a state on the parent component, then pass it as a prop to the other child (see above example). The sibling can then use the data as a prop. Passing data between React components can be a little tricky at first ...
🌐
ITNEXT
itnext.io › passing-data-between-sibling-components-in-react-using-context-api-and-react-hooks-fce60f12629a
Passing data between sibling components in React using Context API and React Hooks | by Valentyn Bilousov | ITNEXT
October 8, 2019 - I will build a simple react app with 2 inputs, where their values will be completely synchronized. In this article I will explain how easy to send data between react sibling components using the most recent react features.
🌐
Medium
medium.com › @haixiang6123 › react-js-component-communication-between-sibling-components-1fdd21328c64
React: Component Communication between Sibling Components | by Haixiang Yan | Medium
December 20, 2018 - Generally, we apply assigning callback and props to implement communication between components in React. However, sometimes it’s hard to implement if we want to pass data between 2 components with very weak relationship.
🌐
Alex Sidorenko
alexsidorenko.com › blog › react-siblings
How to update the state of a sibling component in React? | Alex Sidorenko
Since siblings in React can't access each other's state, we need to lift the state up to the common parent and then pass it back to both children as props. Sounds complicated? Here's a simple visual step-by-step guide 👇 · First, let's lift ...