React Hook: отправка данных от дочернего компонента к родительскому

Я ищу самое простое решение для передачи данных от дочернего компонента к его родителю.

Я слышал об использовании контекста, передаче через свойства или обновлении реквизитов, но я не знаю, какое из них является лучшим решением.

Я создаю интерфейс администратора с PageComponent, который содержит ChildComponent с таблицей, где я могу выбрать несколько строк. Я хочу отправить своему родительскому PageComponent номер строки, которую я выбрал в своем ChildComponent.

Что-то такое :

Компонент страницы:

<div className = "App">
  <EnhancedTable />         
  <h2>count 0</h2>
  (count should be updated from child)
</div>

Дочерний компонент:

 const EnhancedTable = () => {
     const [count, setCount] = useState(0);
     return (
       <button onClick = {() => setCount(count + 1)}>
          Click me {count}
       </button>
     )
  };

Я уверен, что это довольно просто сделать, я не хочу использовать для этого избыточность.

Как насчет того, чтобы использовать хуки на PageComponent и отправить их (и count, и setCount через props в компонент EnhancedTable?

mfakhrusy 17.04.2019 13:50
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
93
1
143 062
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Обычный метод для таких ситуаций — поднять состояние вверх к первому общему предку всех компонентов, которым необходимо использовать состояние (то есть PageComponent в данном случае), и передать состояние и функции, изменяющие состояние, дочерним компонентам в качестве реквизита.

Пример

const { useState } = React;

function PageComponent() {
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1)
  }

  return (
    <div className = "App">
      <ChildComponent onClick = {increment} count = {count} />         
      <h2>count {count}</h2>
      (count should be updated from child)
    </div>
  );
}

const ChildComponent = ({ onClick, count }) => {
  return (
    <button onClick = {onClick}>
       Click me {count}
    </button>
  )
};

ReactDOM.render(<PageComponent />, document.getElementById("root"));
<script src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id = "root"></div>

Да, но мне нужно, чтобы функция увеличения находилась внутри ChildComponent. А затем обновите Parent с результатом.

Kaherdin 17.04.2019 14:00

Спасибо, чувак, ты спас меня от ужасов forwardRef. Это работает на моем проекте.

Manny Alvarado 05.03.2020 07:33

Проблема в том, что если у меня есть const increment (value) => { console.info(value) -> реальное значение, которое я получил от дочернего элемента c setState(value) console.info(state) -> undefined } Но после второго callbackCall Я получил значение предыдущего состояния. Как это исправить?

Hubi 10.04.2020 11:12

Большое спасибо. Это действительно помогло мне

Kangkan Lahkar 21.09.2021 16:05
Ответ принят как подходящий

Вы можете создать метод в своем родительском компоненте, передать его дочернему компоненту и вызывать его из реквизита каждый раз, когда изменяется состояние дочернего элемента, сохраняя состояние в дочернем компоненте.

    const EnhancedTable = ({ parentCallback }) => {
        const [count, setCount] = useState(0);
        
        return (
            <button onClick = {() => {
                const newValue = count + 1;
                setCount(newValue);
                parentCallback(newValue);
            }}>
                 Click me {count}
            </button>
        )
    };

    class PageComponent extends React.Component { 
        callback = (count) => {
            // do something with value in parent component, like save to state
        }

        render() {
            return (
                <div className = "App">
                    <EnhancedTable parentCallback = {this.callback} />         
                    <h2>count 0</h2>
                    (count should be updated from child)
                </div>
            )
        }
    }

но теперь может ли this.callback вызвать повторный рендеринг без необходимости?

ecoe 24.07.2019 20:14

@ecoe, конечно, может, зависит от того, что именно делает обратный вызов. Вызов каких-то внешних функций/диспетчерских действий должен быть относительно безопасным, установка родительского состояния — не очень. Определенно, это не самый чистый код, поэтому, если это возможно, следует использовать подходы из других ответов.

maktel 25.07.2019 10:50

Чтобы упростить задачу, вы можете поделиться установщиками состояния с дочерними элементами, и теперь у них есть доступ для установки состояния его родителя.

пример: Предположим, что есть 4 компонента, как показано ниже,

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

const GrandParent = () => {
  const [name, setName] = useState("i'm Grand Parent");
  return (
    <>
      <div>{name}</div>
      <Parent setName = {setName} />
    </>
  );
};

const Parent = params => {
  return (
    <>
      <button onClick = {() => params.setName("i'm from Parent")}>
        from Parent
      </button>
      <Child setName = {params.setName} />
    </>
  );
};

const Child = params => {
  return (
    <>
      <button onClick = {() => params.setName("i'm from Child")}>
        from Child
      </button>
    </>
  );
};

таким образом, компонент прародителя имеет фактическое состояние, и, разделяя метод установки (setName) для родителя и дочернего элемента, они получают доступ для изменения состояния прародителя.

вы можете найти рабочий код в песочнице ниже, https://codesandbox.io/embed/async-fire-kl197

Пожалуйста, предоставьте важную информацию по ссылке, потому что срок действия ссылки может истечь в будущем.

Abhishek Gurjar 22.07.2019 13:18

Спасибо, это было полезно.

Yaks10 18.08.2021 17:29

Мне пришлось столкнуться с аналогичной проблемой, и я нашел другой подход, используя объект для ссылки на состояния между различными функциями и в том же файле.

import React, { useState } from "react";

let myState = {};

const GrandParent = () => {
  const [name, setName] = useState("i'm Grand Parent");
  myState.name=name;
  myState.setName=setName;
  return (
    <>
      <div>{name}</div>
      <Parent />
    </>
  );
};
export default GrandParent;

const Parent = () => {
  return (
    <>
      <button onClick = {() => myState.setName("i'm from Parent")}>
        from Parent
      </button>
      <Child />
    </>
  );
};

const Child = () => {
  return (
    <>
      <button onClick = {() => myState.setName("i'm from Child")}>
        from Child
      </button>
    </>
  );
};

Я действительно не уверен, что это правильный способ использования useState. Я бы рекомендовал внимательно следить за официальной документацией (reactjs.org/docs/hooks-state.html). в вашем ответе выше вам не нужен «myState», вы можете просто использовать переменные name и setName из useState. Просто подумайте, хотите ли вы получить значение переменной, то есть «имя», используйте первую переменную. если вы хотите установить переменную, используйте вторую переменную, то есть setName. Честная игра, хорошая работа для попытки найти собственное решение, но иногда это заканчивается беспорядком. Придерживайтесь лучших практик и официальной документации.

Andrew Irwin 11.12.2019 17:50

Я должен был сделать это в введите сценарий. Объектно-ориентированный аспект потребует от разработчика добавления этого метода обратного вызова в качестве поля в интерфейсе после наследования от родителя, и тип этой опоры будет Функция. Я нашел это крутым!

Другие вопросы по теме

Обязательно инициируйте асинхронный запрос с помощью хуков React
React Hooks Mobx: неверный вызов ловушки. Хуки можно вызывать только внутри тела функционального компонента
Использование хука React для запуска метода Mobx перед первоначальным рендерингом компонента
Реагируйте на useEffect Hook, когда изменяется только одно из зависимостей эффекта, но не другие
Как дождаться установки значения контекста | Реагировать на хуки
Состояние подъема с помощью крючков (из сопоставленного массива)
Как настроить таргетинг на определенный элемент для переключения кликов с помощью React Hooks?
React обновляет объект состояния с помощью хуков (useState) работает, но не перерисовывает
Реагируйте на состояние обновления нажатием кнопки, используя useState
Реакция с использованием useState/Hooks в HOC вызывает ошибку «Хуки могут вызываться только внутри тела функционального компонента»