恕我直言React Hooks FAQ #getDerivedStateFromProps的建议
导致一个第一次渲染,其值row
与isScrollingDown
的值不对应。由于对setIsScrollingDown
的调用只会安排新的渲染,并且不会影响当前的渲染,因此将使用新的row
值和旧的isScrollingDown
值执行当前渲染。>
此行为与组件类的静态getderivedstatefromprops
方法不同,该方法允许row
和isScrollingDown
之间保持一致。
是否应使用类似以下代码的示例来更新示例,以确保连贯的呈现?还是我错过了什么?
谢谢!
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}`;
}
答案 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);