简体   繁体   English

试图从 ReactJS 中的孩子的孩子那里获取数据

[英]Trying to get data from child of a child in ReactJS

I've read that you can't really pass props upwards like that, but you can do so through functions.我读过你不能像那样真正向上传递道具,但你可以通过函数来做到这一点。 I went and found a workaround and it worked.我去找了一个解决方法,它奏效了。

My problem is: I'm trying to get data to App from 2 layers down - App > DataInput > ValidateUser - so I can pass it over from App to 2 other different components that have nothing to do with filling the form.我的问题是:我正在尝试从 2 层向下获取数据到 App - App > DataInput > ValidateUser - 所以我可以将它从 App 传递到与填写表单无关的 2 个其他不同组件。

I can get the data from ValidateUser back to DataInput , just before sending it to App I'm logging the result and it's all as expected.我可以将数据从ValidateUser返回到DataInput ,就在将其发送到 App 之前,我正在记录结果,这一切都符合预期。 The problem begins when I try to send it to App and the data I receive is undefined.当我尝试将其发送到 App 并且我收到的数据未定义时,问题就开始了。

I checked a few times to see if I was making a typo or logical error while implementing the second data call.我检查了几次,看看我在执行第二次数据调用时是否犯了错字或逻辑错误。 Unless I completely missed it, nothing.除非我完全错过它,否则什么都没有。 I started to think that, maybe, then, the problem might be with the execution order.我开始认为,也许,问题可能出在执行顺序上。 App is read first so, maybe, it wasn't getting updated once I assigned the value further down the execution line?应用程序首先被读取,所以,也许,一旦我将值分配到执行线的下方,它就没有得到更新? But then, I'm updating the state when I click the button and it prints out the undefined and the blank object again being called from App while I can see the object is fully filled when it's last called over the handler in DataInput…但是,当我单击按钮时,我正在更新 state,它会打印出未定义和空白的 object 再次从 App 调用,而我可以看到 object 中的处理程序数据输入已完全填充时

I'm probably missing something here.我可能在这里遗漏了一些东西。

App应用程序

import "./App.css";
import Box from "@mui/material/Box";
import React from "react";
import DataInput from "./components/DataInput";
import UserDataTable from "./components/UserDataTable";

const App = () => {
  let userData;
  let formSubmited = false;

  const getUserData = (params) => {
      console.log(params);
      userData = { ...userData, ...params };
      console.log(userData);
  };

  return (
    <div className="App">
      <Box
        sx={{
          width: 1000,
          height: 600,
          backgroundColor: "rgba(197, 202, 255, 1)",
          m: 4,
          border: 1.4,
          borderColor: "rgba(140, 150, 255, 1)",
        }}
      >
        <DataInput sendData={getUserData} />

        <UserDataTable />

        <div className="Author">
          <h3>André Lourenço</h3>
        </div>
      </Box>
    </div>
  );
};

export default App;

DataInput数据输入

import {
  TextField,
  Select,
  MenuItem,
  FormControl,
  InputLabel,
} from "@mui/material";
import { LoadingButton } from "@mui/lab";
import React, { useRef, useState } from "react";
import SaveIcon from "@mui/icons-material/Save";
import "../styles/DataInput.css";
import ValidateUser from "./ValidateUser";

export default function DataInput(props) {
  //State & Ref Hooks
  const [country, setCountry] = useState("");

  const handleCountryChange = (event) => setCountry(event.target.value);

  const countryInputRef = useRef();
  const nameInputRef = useRef();
  const surnameInputRef = useRef();
  const birthdayInputRef = useRef();

  const [rawData, setRawData] = useState("");

  // I/O
  let returnUserData;

  const handleFormSubmission = (event) => {
    event.preventDefault();

    let data = {
      name: "",
      surname: "",
      country: "",
      birthday: "",
    };

    data.name = nameInputRef.current.value;
    data.surname = surnameInputRef.current.value;
    data.country = countryInputRef.current.value;
    data.birthday = birthdayInputRef.current.value;

    setRawData(data);
  };

  const getValidatedData = (params) => {
    returnUserData = { ...returnUserData, ...params };
    returnUserData.isSubmited = true;
    console.log(returnUserData);
  };

  const handleSendData = (data) => props.sendData(data);

  return (
    <div className="DataInput">
      <form>
        <div className="Input-Boxes">
          <div className="Box-Name">
            <TextField
              sx={{ input: { color: "blue" } }}
              label="Name"
              inputRef={nameInputRef}
              required
            />
          </div>

          <div className="Box-Surname">
            <TextField
              sx={{ input: { color: "blue" } }}
              label="Surname"
              inputRef={surnameInputRef}
              required
            />
          </div>

          <div className="Box-Country">
            <FormControl variant="filled" sx={{ minWidth: 220 }}>
              <InputLabel id="demo-simple-select-filled-label">
                Countries
              </InputLabel>

              <Select
                required
                labelId="demo-simple-select-filled-label"
                id="demo-simple-select-filled"
                label="Countries"
                value={country}
                autoWidth
                onChange={handleCountryChange}
                inputRef={countryInputRef}
              >
                <MenuItem value={"Brazil"}> Brazil </MenuItem>
                <MenuItem value={"Portugal"}> Portugal </MenuItem>
              </Select>
            </FormControl>
          </div>

          <div className="Box-Birthday">
            <TextField
              sx={{ input: { color: "blue" } }}
              label="Birthday"
              inputRef={birthdayInputRef}
              type="date"
              InputLabelProps={{ shrink: true }}
              required
            />
          </div>
        </div>

        <div className="Button-Save">
          <LoadingButton
            loadingPosition="end"
            endIcon={<SaveIcon />}
            variant="outlined"
            type="submit"
            onClick={handleFormSubmission}
          >
            Save
          </LoadingButton>
          <ValidateUser data={rawData} sendData={getValidatedData} />
        </div>
      </form>

      {handleSendData(returnUserData)}
    </div>
  );
}

Trying to find a work around to get data back up to the parent components has never worked to well for me.试图找到一种解决方法将数据备份到父组件对我来说从来没有奏效过。 I would recommend using a library such as Redux.我建议使用诸如 Redux 之类的库。 With Redux you can put data in its current state into a Store.使用 Redux,您可以将当前 state 中的数据放入存储中。 This data can then be called into any component within your React App.然后可以将这些数据调用到 React 应用程序中的任何组件中。 React-Redux has hooks that allows you to get this data. React-Redux具有允许您获取此数据的挂钩。 Although Redux does take a good amount of set-up and a learning curve it might work for your projects needs.尽管 Redux 确实需要大量的设置和学习曲线,但它可能适合您的项目需求。 Redux-Toolkit can help with some of the set-up. Redux-Toolkit可以帮助进行一些设置。

Some tips on using Redux.使用 Redux 的一些技巧。 Redux wraps your React app, so make sure that you don't miss this step. Redux包装了您的 React 应用程序,因此请确保您不要错过这一步。 Your gonna need a Store that will hold the current state of your data.您将需要一个存储当前 state 数据的存储。 Your gonna use hooks to store and get your data.您将使用钩子来存储和获取您的数据。 Primarily the useDispatch hook to update your Store data and useSelector to grab your data.主要是 useDispatch 钩子来更新你的 Store 数据和 useSelector 来获取你的数据。

Once you have Redux all set-up you can do useDispatch(returnUserData) .一旦你有 Redux 所有设置你可以做useDispatch(returnUserData) To save your data to the store.将您的数据保存到商店。 You could then call the data into App.js using let data = useSelector(state => state.data.setdata) .然后,您可以使用let data = useSelector(state => state.data.setdata)将数据调用到 App.js 中。 Of course what is actually inside of useSelector needs to match your Store set-up.当然,useSelector 内部的实际内容需要与您的 Store 设置相匹配。

Your implementation to send data to App component is correct.您将数据发送到 App 组件的实现是正确的。 But you don't need handleSendData function and you are calling it from return which is wrong.但是您不需要handleSendData function 并且您从返回中调用它是错误的。 You can send data to App from inside getValidatedData function like below.您可以从getValidatedData function 内部向 App 发送数据,如下所示。

const getValidatedData = (params) => {
   returnUserData = { ...returnUserData, ...params };
   returnUserData.isSubmited = true;
   console.log(returnUserData);
   props.sendData(returnUserdata)

 };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM