React Hooks常见问题解答:getpropivedstatefromprops的实现导致呈现不一致状态的渲染

时间:2019-03-08 15:36:22

标签: reactjs react-hooks getderivedstatefromprops

恕我直言React Hooks FAQ #getDerivedStateFromProps的建议  导致一个第一次渲染,其值rowisScrollingDown的值不对应。由于对setIsScrollingDown的调用只会安排新的渲染,并且不会影响当前的渲染,因此将使用新的row值和旧的isScrollingDown值执行当前渲染。

此行为与组件类的静态getderivedstatefromprops方法不同,该方法允许rowisScrollingDown之间保持一致。

是否应使用类似以下代码的示例来更新示例,以确保连贯的呈现?还是我错过了什么?

谢谢!

function ScrollView({row}) {
    let [isScrollingDown, setIsScrollingDown] = useState(false);
    let [prevRow, setPrevRow] = useState(null);

    if (row !== prevRow) {
        // Row changed since last render. Update isScrollingDown.
        isScrollingDown = prevRow !== null && row > prevRow
        setIsScrollingDown(isScrollingDown);
        setPrevRow(row);
    }

    return `Scrolling down: ${isScrollingDown}`;
}

1 个答案:

答案 0 :(得分:0)

以下是文档中的重要组成部分,无需进行更改:

  

React将在之后立即以更新后的状态重新运行组件   退出第一个渲染器,这样就不会很昂贵。

与它们不同步的渲染将永远不会提交给浏览器。实际上,如果要从渲染器返回子组件,则直到状态更新后才执行子组件的渲染(从渲染器返回的更新了状态的子组件将被忽略)。

以下是添加了控制台日志以显示此内容的示例。请注意,当您增加行数时,ScrollView呈现两次,但ScrollingDown仅呈现一次,仅接收到ScrollView状态的最新版本。

import React, { useState } from "react";
import ReactDOM from "react-dom";

function ScrollingDown({ isScrollingDown, prevRow, row }) {
  console.log("ScrollingDown", isScrollingDown, prevRow, row);
  return (
    <div>
      {`Scrolling down: ${isScrollingDown}`}
      <br />
      {`prevRow: ${prevRow}`}
      <br />
      {`row: ${row}`}
    </div>
  );
}

function ScrollView({ row }) {
  let [isScrollingDown, setIsScrollingDown] = useState(false);
  let [prevRow, setPrevRow] = useState(null);

  if (row !== prevRow) {
    // Row changed since last render. Update isScrollingDown.
    setIsScrollingDown(prevRow !== null && row > prevRow);
    setPrevRow(row);
  }
  console.log("ScrollView", isScrollingDown, prevRow, row);
  return (
    <ScrollingDown
      isScrollingDown={isScrollingDown}
      prevRow={prevRow}
      row={row}
    />
  );
}

function App() {
  const [row, setRow] = useState(1);
  return (
    <div className="App">
      <ScrollView row={row} />
      <button onClick={() => setRow(prev => prev + 1)}>Increment Row</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit Hooks getDerivedStateFromProps