Передача реквизита / состояния между двумя функциональными дочерними компонентами в React?

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

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

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

Паэрент

import React, { useState } from "react";
import ShoppingPageOne from "./ShoppingPageOne";
import ShoppingPageTwo from "./ShoppingPageSecond";

function ShoppingPageContainer() {

  const [pageone_Open, setPageone_Open] = useState(true);
  const [pagetwo_Open, setPagetwo_Open] = useState(false);


  const page_showHandler = () => {
    setPageone_Open(!pageone_Open);
    setPagetwo_Open(!pagetwo_Open);
  };

  return (
    <div className="Shopping_Container">
      <div className="Shopping_Box">
        <h2>Online food shop</h2>
        <div className="Shopping_Page_Container">
          <ShoppingPageOne showOne={pageone_Open} next_ClickHandler={page_showHandler} />
          <ShoppingPageTwo showTwo={pagetwo_Open} Reset_Data={page_showHandler} />
        </div>
      </div>
    </div>
  );
}

export default ShoppingPageContainer;

Первый ребенок:

import React, { useState, useEffect } from "react";
import Data from '../shoppingData/Ingredients';

const ShoppingPageOne = (props) => {

  //element displays
  const [pageone_show, setPageone_show] = useState("pageOne");

  //stores quantities of items as JSON objects
  const [Quantities, setQuantities] = useState({});
  const [QuantiesProps, setQuantitiesProps] = useState(null)


  useEffect(() => {
    //sets info text using Json
    if (props.showOne) {
      setPageone_show("pageOne");
    } else {
      setPageone_show("pageOne hide");
    }
  }, [props.showOne]);


  return (
    <div className={"Shopping_Content " + pageone_show}>
      {Data.map((Ingredients) => {

        //updates Quanties Hook
        const handleChange = (event) => {

          setQuantities({
            ...Quantities,
            [Ingredients.Name]: {
              ...(Quantities[Ingredients.Name] ?? {}),
              quantities: event.target.value
            }
          });
        };

        return (<div className="Shopping_input" key={Ingredients.Name}>
          <p>{Ingredients.Name} £{Ingredients.Price}</p>
          <input onChange={handleChange.bind(this)} min="0" type="number"></input>
        </div>)
      })}
      <div className="Shopping_Buttons">
        <p onClick={props.next_ClickHandler}>Buy Now!</p>
      </div>

    </div>
  );
};

export default ShoppingPageOne;

Второй ребенок

import React, { useState, useEffect } from "react";
import Data from '../shoppingData/Ingredients';

const ShoppingPageSecond = (props) => {
  //element displays
  const [pagetwo_show, setPagetwo_show] = useState("pageTwo hide");

  useEffect(() => {
    //resets info text
    if (props.showTwo) {
      setPagetwo_show("pageTwo");
    } else {
      setPagetwo_show("pageTwo hide");
    }


  }, [props.showTwo]);




  return (
    <div className={"Shopping_Content " + pagetwo_show}>

      <div className="Shopping_Buttons">
        <p onClick={props.Reset_Data}>Shop Again</p>
      </div>

    </div>
  );
};

export default ShoppingPageSecond;import React, { useState, useEffect } from "react";
import Data from '../shoppingData/Ingredients';

const ShoppingPageSecond = (props) => {
  //element displays
  const [pagetwo_show, setPagetwo_show] = useState("pageTwo hide");

  useEffect(() => {
    //resets info text
    if (props.showTwo) {
      setPagetwo_show("pageTwo");
    } else {
      setPagetwo_show("pageTwo hide");
    }


  }, [props.showTwo]);




  return (
    <div className={"Shopping_Content " + pagetwo_show}>

      <div className="Shopping_Buttons">
        <p onClick={props.Reset_Data}>Shop Again</p>
      </div>

    </div>
  );
};

export default ShoppingPageSecond;

Я просто хочу передать состояние, содержащееся в хуке Quantities, из первого ребенка в второго ребенка при покупке сейчас! кнопка нажата. Как лучше всего это сделать?


person lukeet    schedule 04.12.2020    source источник
comment
Есть два способа: сохранить состояние в общем предке и передать его по дереву вручную или использовать context API, чтобы сделать это за вас. Пример в документации предназначен для настройки темы. Я часто использую его для вещей, необходимых на нескольких уровнях, таких как тема или детали для вошедшего в систему пользователя. С таким неглубоким деревом я бы, наверное, просто сделал это вручную.   -  person Jared Smith    schedule 04.12.2020
comment
Спасибо, Джаред. Я прочитаю, что API контекста звучит очень полезно! При этом, какой метод вы бы порекомендовали из этих двух?   -  person lukeet    schedule 04.12.2020
comment
Для двух компонентов, которые являются братьями и сестрами, я бы сохранил состояние в родительском элементе. Если узлы не являются родственниками или я думаю, что мне могут понадобиться данные на нескольких уровнях дерева рендеринга, я вставлю их в контекст. Например, вместо того, чтобы иметь состояние pageOpen для каждой страницы, я мог бы просто сохранить состояние currentPage в контексте и, возможно, сделать его более доступным?   -  person Jared Smith    schedule 04.12.2020
comment
Я реализовал контекстный API, очень простой в использовании, большое спасибо   -  person lukeet    schedule 05.12.2020
comment
Нет проблем, рад, что ты понял.   -  person Jared Smith    schedule 05.12.2020


Ответы (1)


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

import React, { useState } from 'react';

const PageOne = ({ value, setValue }) => {
   const PageOneFunction = () => {
      setValue({
         pageOneData: value.pageOneData + 1,
         pageTwoData: value.pageTwoData + 1,
      });
   };

   return (
      <div>
         <h4>Page One</h4>
         <div>{value.pageOneData}</div>
         <button onClick={PageOneFunction}>
            Increase page one and page two value
         </button>
      </div>
   );
};

const PageTwo = ({ value, setValue }) => {
   const pageTwoFunction = () => {
      setValue({
         pageOneData: 0,
         pageTwoData: 0,
      });
   };

   return (
      <div>
         <h4>Page Two</h4>
         <div>{value.pageTwoData}</div>
         <button onClick={pageTwoFunction}>Reset</button>
      </div>
   );
};

const PageContainer = () => {
   const [data, setData] = useState({
      pageOneData: 0,
      pageTwoData: 0,
   });

   return (
      <div className="bg-white">
         <PageOne value={data} setValue={setData} />
         <PageTwo value={data} setValue={setData} />
      </div>
   );
};

export default PageContainer;
person Charles    schedule 04.12.2020
comment
Это можно было бы назвать ответом, если бы вы включили пример в рабочий код. - person Jared Smith; 04.12.2020
comment
В моем примере кода, как это будет работать, если я перемещаю хук Quantities на родительский элемент? как мне обновить перехватчик, используя поля ввода на первом дочернем элементе, и передать их второму дочернему элементу? какие ссылки с примерами можете предоставить? - person lukeet; 04.12.2020