【问题标题】:React render madnessReact 渲染疯狂
【发布时间】:2021-01-21 21:48:02
【问题描述】:

我正在使用 React 钩子和功能组件。在我的功能组件中,我发生了一些我无法摆脱的奇怪事情。在 useEffect 中,最初我没有返回数组来防止无限循环,并试图在 deleteClickedHandler 中使用 rowData,但它始终为空。在一些研究表明解决此问题的方法是使用 useRef 之后,这似乎有效,但引发了 ESLinter 的愤怒,它要求将 rowData 放在导致重新渲染 useEffect 的数组中。这会导致 deleteClickedHandler 从 rowDataRef.current 接收数据,但会导致无限循环。

deleteClickedHandler 正在执行乐观并发,改变 rowData 状态,并与 api 交互。

几个小时后,我不知道如何解决这个问题。

如果我从告诉 useEffect 何时重新渲染的数组中删除 rowData,delete 处理程序会工作但不会重新渲染,并且由于 deleteClickedHandler 是一个处理程序,我无法确定如何在没有无穷无尽的情况下导致重新渲染循环。

我确定我在做一些愚蠢的事情,但无法确定为什么在 deleteClickedHandler 中 rowData 不可用 - 我知道处理程序是闭包的一种形式,但 rowData 是状态。

const initialState = {
  id: 0,
  credit: false,
  transactionAmount: 0,
  accountBalance: 0,
  transactionDate: new Date(),
  confirmation: "",
  comment: "",
  action: "EDIT",
};

const SERVER_URL='/api/checking';  //process.env.REACT_APP_SERVER_URL;

function Checking() {
  const [rowData, setRowData] = useState([]);
  const [newData, setNewData] = useState(initialState);
  const [displayModal, setModalDisplay] = useState(false);
  const columnDefinitions = Columns();
  const rowDataRef = useRef(rowData);

  useEffect(() => {
    fetch(SERVER_URL)
      .then((response) => response.json())
      .then((rowData) => setRowData(rowData));

    rowDataRef.current = rowData;
  }, [rowData]);

  function deleteClickedHandler(props) {
    let fetchUrl = SERVER_URL + "/" + props.id;
    let balance = 0.0;
    let transactionAmount = 0.0;
    let data = rowDataRef.current;

    if (
      data.length > 0 &&
      window.confirm("Are you sure you wish to delete transaction: " + props.id)
    ) {
      for (let i = 0; i < data.length; i++) {
        transactionAmount = props.credit
          ? props.transactionAmount
          : -1.0 * props.transactionAmount;
        balance = balance + transactionAmount;

        if (data[i].id === props.id) {
          data.splice(i, 1);
        }

        if (data[i].id > props.id) {
          data[i].accountBalance = balance;
        }
      }

      setRowData(data);
      CustomFetch(fetchUrl, "DELETE");
    }
  }

  function rowActionHandler(props) {
    switch (props.action) {
      case "DELETE":
        deleteClickedHandler(props);
        break;
      default:
        break;
    }
  }

  const context = { componentParent: rowActionHandler };

编辑 1

下面清理了无限渲染,允许delete通过rowDataRef访问rowData,但delete后不会重新渲染。如何让删除的重新渲染工作?

  useEffect(() => {
    fetch(SERVER_URL)
      .then((response) => response.json())
      .then((rowData) => {
        setRowData(rowData)
        rowDataRef.current = rowData;
      });
  }, []);

【问题讨论】:

  • 您究竟希望useEffect 何时运行?据我所知,效果本身会导致无限的重新渲染+请求,除了你上面描述的。
  • 我希望它在加载和 rowData 更改时运行

标签: reactjs react-hooks react-functional-component


【解决方案1】:

虽然不理想,但有一种解决方法,与我手动执行的操作相同。这是使用以下语句强制页面重新加载。如果有人可以提供状态方法,我愿意改变这个答案。

window.location.reload();

【讨论】:

    猜你喜欢
    • 2011-11-25
    • 2018-08-22
    • 2011-03-05
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多