gpt4 book ai didi

javascript - 从组件中的 useState 多次调用状态更新程序会导致多次重新渲染

转载 作者:行者123 更新时间:2023-12-03 21:08:18 26 4
gpt4 key购买 nike

我第一次尝试 React 钩子(Hook),一切似乎都很好,直到我意识到当我获取数据并更新两个不同的状态变量(数据和加载标志)时,我的组件(数据表)被渲染两次,即使两个调用状态更新程序发生在同一个函数中。这是我的 api 函数,它将两个变量都返回给我的组件。

const getData = url => {

const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(async () => {

const test = await api.get('/people')

if(test.ok){
setLoading(false);
setData(test.data.results);
}

}, []);

return { data, loading };
};

在一个普通的类组件中,您将进行一次调用来更新可能是一个复杂对象的状态,但“ Hook 方式”似乎是将状态拆分为更小的单元,其副作用似乎是多个重新当它们单独更新时呈现。任何想法如何减轻这种情况?

最佳答案

您可以结合 loading状态和 data状态转换为一个状态对象,然后你可以做一个 setState调用,只会有一个渲染。

注:不同于 setState在类组件中,setStateuseState 返回不会将对象与现有状态合并,它会完全替换对象。如果要进行合并,则需要读取先前的状态并自己将其与新值合并。引用 docs .

在您确定存在性能问题之前,我不会过多担心过度调用渲染。渲染(在 React 上下文中)和将虚拟 DOM 更新提交到真实 DOM 是不同的事情。这里的渲染是指生成虚拟 DOM,而不是更新浏览器 DOM。 React 可以批量处理 setState调用并使用最终的新状态更新浏览器 DOM。

const {useState, useEffect} = React;

function App() {
const [userRequest, setUserRequest] = useState({
loading: false,
user: null,
});

useEffect(() => {
// Note that this replaces the entire object and deletes user key!
setUserRequest({ loading: true });
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
setUserRequest({
loading: false,
user: data.results[0],
});
});
}, []);

const { loading, user } = userRequest;

return (
<div>
{loading && 'Loading...'}
{user && user.name.first}
</div>
);
}

ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>


替代方案 - 编写您自己的状态合并钩子(Hook)

const {useState, useEffect} = React;

function useMergeState(initialState) {
const [state, setState] = useState(initialState);
const setMergedState = newState =>
setState(prevState => Object.assign({}, prevState, newState)
);
return [state, setMergedState];
}

function App() {
const [userRequest, setUserRequest] = useMergeState({
loading: false,
user: null,
});

useEffect(() => {
setUserRequest({ loading: true });
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
setUserRequest({
loading: false,
user: data.results[0],
});
});
}, []);

const { loading, user } = userRequest;

return (
<div>
{loading && 'Loading...'}
{user && user.name.first}
</div>
);
}

ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>

关于javascript - 从组件中的 useState 多次调用状态更新程序会导致多次重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54755483/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com