Двустороннее связывание между компонентами

К примеру есть приложение react, с двумя компонентами

import './App.css';
import React from 'react';

function Child() {
  const [value, setValue] = React.useState('1')
  return (
    <h1>{value}</h1>
  )
}

function Another() {
  return (
    <input value={'1'} onChange={el => console.log(el.target.value)}></input>
  )
}

function App() {
  return (
    <div className="App">
      <Another />
      <Child />
    </div>
  );
}

export default App;

Задача компоненты Another изменять поле value в компоненте Child. Как сделать двустороннее связывание в соседнюю компоненту?


Ответы (2 шт):

Автор решения: Данил Веников

import { useState } from 'react'

function App() {
  const [value, setValue] = useState('1')
  return (
    <div className="App">
      <input onChange={(event) => setValue(event.target.value)}></input>
      <h1>{value}</h1>
    </div>
  )
}

export default App

→ Ссылка
Автор решения: EzioMercer

Прошу прощения за нестандартный вид React кода, но по другому в Code Snippets не вставишь рабочий React. Вот пример того как вам это следует делать:

const {useState} = React;

function Child({title}) {
  return (
    <h1>{title}</h1>
  )
}

function Another({setValue, value}) {
  return (
    <input value={value} onChange={el => setValue(el.target.value)}></input>
  )
}

function App() {
  const [value, setValue] = useState('1');
  
  return (
    <div className="App">
      <Another setValue={setValue} value={value}/>
      <Child title={value} />
    </div>
  );
}

ReactDOM.render(<App/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

Хочу немного дополнить ответ:

То что я предложил - это далеко не единнственный способ реализовать то что вам надо. Я лишь пошёл по простому пути и сделал именно вашим стилем.

В больших приложениях скорее всего такой подход будет губительным, особенно, если надо будет чтобы не просто соседние дочерние элементы общались между собой , а элементы, которые находятся "далеко" друг от друга. Тогда вам придётся пробрасывать value в многих местах, а потом при изменениях вспомнить везде где он был использован, чтобы везде поменять (например название). То же самое относится и к setValue.

Чтобы избежать этого "ада" используют в основном либо React Context либо React Redux. Если очень упрощённо объяснить, то суть в том чтобы создать хранилище и чтобы любая компонента в любой момент мог обратиться за значением или изменить значение (при этом все кто слушали изменение значения автоматически будут перерисованы с новым значением)

→ Ссылка