reactjs - 努力将数据从子组件传递到父 React 组件。渲染不同组件 (`Table`) 时无法更新组件 (`App`)

我的目标是根据单击的列对 table 的数据进行排序。为了实现这个目标,我需要将关于 header 点击的信息从 child component "Table" 传递给 parent component “App”。

这是来自 child component Table

const [keyclicked, setKeyclicked] = React.useState("");

  const [sortOptions, setSortOptions] = React.useState({
    first: "",
    second: ""
  });

  const modalFunct = React.useMemo(() => {
    if (document.getSelection(keyclicked.target).focusNode !== null) {
      console.log(
        document
          .getSelection(keyclicked.target)
          .focusNode.wholeText.toLowerCase()
      );
      let newsorting = sortOptions;
      if (sortOptions.first !== "") {
        newsorting.second = document
          .getSelection(keyclicked.target)
          .focusNode.wholeText.toLowerCase();
      } else {
        newsorting.first = document
          .getSelection(keyclicked.target)
          .focusNode.wholeText.toLowerCase();
      }
      setSortOptions(newsorting);
      selectSorter(
        document
          .getSelection(keyclicked.target)
          .focusNode.wholeText.toLowerCase()
      );
    }
  }, [keyclicked]);

  const renderHeader = () => {
    let headerElement = ["id", "name", "email", "phone", "operation"];

    return headerElement.map((key, index) => {
      return (
        <th onClick={setKeyclicked} key={index}>
          {key.toUpperCase()}
        </th>
      );
    });
  };

  const renderBody = () => {
    console.log("renderBody-employees: ", employees);

    return employees.map(({ id, name, email, phone }) => {
      return (
        <tr key={id}>
          <td>{id}</td>
          <td>{name}</td>
          <td>{email}</td>
          <td>{phone}</td>
          <td className="operation">
            <button className="button" onClick={() => removeData(id)}>
              Delete
            </button>
          </td>
        </tr>
      );
    });
  };

  return (
    <>
      <h1 id="title">Table</h1>
      <h3>
        {" "}
        Lets go for a <FaBeer /> ?{" "}
      </h3>
      <table id="employee">
        <thead>
          <tr>{renderHeader()}</tr>
        </thead>
        <tbody>{renderBody()}</tbody>
      </table>
    </>
  );
};

export default Table;

这是来自 App.js

import Table from "./Table";

  const [selectedSortingOption, SetSelectedSortingOption] = React.useState(
    null
  );


  return (
<div className="App">
  <div align="center">
    <button onClick={addSingleEmployee}>AddEmployee</button>

    <Select
      defaultValue={selectedSortingOption}
      onChange={SetSelectedSortingOption}
      options={sortingOptions}
    />
  </div>
  <div className="scrollable">
    <Table
      table_data={sortedData}
      row_data={newEmployee}
      basePageLink={""}
      removeData={removeRaw}
      selectSorter={selectHowToSort}
    />
  </div>
  <div align="center">
    <button onClick={emptyTable}>EmptyTable</button>
  </div>
</div>

); }

例如,当单击 email 标头时,我在控制台日志中得到以下输出:

`email` : which is correct

而这个 warning - 错误信息:

Warning: Cannot update a component (`App`) while rendering a different component (`Table`). To locate the bad setState() call inside `Table`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
Table@https://oqx8ut.csb.app/src/Table/index.jsx:23:15
div
div
App@https://oqx8ut.csb.app/src/App.js:168:33

Table/index.jsx:23 指的是这一行:

React.useEffect(() => {
    setEmployees(table_data);
    return () => {
      // clean-up function
    };
  }, [table_data]);

App.js:168 指的是这个:

const [selectedSortingOption, SetSelectedSortingOption] = React.useState(
    null
  );

我也尝试在 Child Component "Table" 中这样做:

const [sortOptions, setSortOptions] = React.useState({
    first: "",
    second: ""
  });

  //const modalFunct = (key_clicked) => {
  const modalFunct = React.useMemo(() => {
    //console.log(keyclicked.target);
    //console.log(document.getSelection(keyclicked.target).focusNode);
    if (document.getSelection(keyclicked.target).focusNode !== null) {
      console.log(
        //selectSorter(
        document
          .getSelection(keyclicked.target)
          .focusNode.wholeText.toLowerCase()
      );
      let newsorting = sortOptions;
      if (sortOptions.first !== "") {
        newsorting.second = document
          .getSelection(keyclicked.target)
          .focusNode.wholeText.toLowerCase();
      } else {
        newsorting.first = document
          .getSelection(keyclicked.target)
          .focusNode.wholeText.toLowerCase();
      }
      setSortOptions(newsorting);
      //selectSorter(
        //document
          //.getSelection(keyclicked.target)
          //.focusNode.wholeText.toLowerCase()
      //);
    }
  }, [keyclicked]);

  const memoizedSelectSorter = React.useMemo(() => {
    selectSorter(sortOptions);
  }, [sortOptions]);

但仍然得到同样的错误

我究竟做错了什么?如何将 email 信息(关于单击哪个标题的信息)从 Child component "Table" 传递到要对数据进行排序的 Parent Component "App"

回答1

你在你的代码中搜索这一行:return employees.map(({ id, name, email, phone }) => {,你把 return 放在 Array.map() 之前会给你数组而不是 JSX 语法。尝试删除该行中的 return :

const renderBody = () => {
    console.log("renderBody-employees: ", employees);

    return employees.map(({ id, name, email, phone }) => { //<== remove this return here, put "?" in employees?.map to prevent crash app
      return (
        <tr key={id}>
          <td>{id}</td>
           ....

可能 table_data 在您的 dependency 中使 Table 组件无限重新渲染导致 React 忙于渲染此组件,请尝试将其删除:

React.useEffect(() => {
        setEmployees(table_data);
        return () => {
          // clean-up function
        };
      }, []); // <== Had remove table_data in dependency

相似文章