我无法理解为什么我的App react组件呈现两次,如下面的gif所示。
我在返回组件之前插入了console.log,以查看我的组件渲染了多少次。
每当我删除useState挂钩时,我的应用程序就会按照我认为的那样呈现一次。欢迎就为什么发生这种情况提供任何指导
import React, { useState, useEffect } from 'react';
const ListItem = ({ title, url, author, num_comments, points }) => {
return (
<div>
<span>
<a href={url} target='_blank' rel='noopener noreferrer'>
{title}
</a>{' '}
by {author}
</span>
<br />
<span>Comments: {num_comments}</span>
<br />
<span>Points: {points}</span>
<hr />
</div>
);
};
const List = ({ list }) => {
return list.map(({ objectID, ...item }) => (
<ListItem key={objectID} {...item} />
));
};
const Search = ({ search, onSearch }) => {
return (
<div>
<label htmlFor='search'>Search: </label>
<input id='search' type='text' value={search} onChange={onSearch} />
<p>
Searching for <strong>{search}</strong>
</p>
</div>
);
};
const App = () => {
const stories = [
{
title: 'React',
url: 'https://reactjs.org/',
author: 'Jordan Walke',
num_comments: 3,
points: 4,
objectID: 0,
},
{
title: 'Redux',
url: 'https://redux.js.org/',
author: 'Dan Abramov, Andrew Clark',
num_comments: 2,
points: 5,
objectID: 1,
},
];
const [search, setSearch] = useState(localStorage.getItem('search') || '');
useEffect(() => {
localStorage.setItem('search', search);
}, [search]);
const handleSearch = (event) => {
setSearch(event.target.value);
};
console.log('rendered');
return (
<div className='App'>
<h1>My Hacker Stories</h1>
<Search search={search} onSearch={handleSearch} />
<hr />
<List
list={stories.filter((story) =>
story.title.toLowerCase().includes(search.toLowerCase())
)}
/>
</div>
);
};
export default App;
答案 0 :(得分:4)
检查一下:https://github.com/facebook/react-devtools/issues/1297
“意外重新渲染”实际上不是由useEffect引起的 特别是-而是DevTools“检查”挂钩的方式 通过孤立地重新渲染功能组件来获取值。
尽管我了解到意外的渲染可能表明存在问题 在某些情况下,这个特定的问题对于 几个原因:
渲染不是递归的。 (不渲染子组件。) 渲染仅对于安装了DevTools的用户发生,即使如此- 仅影响单个组件(当前在 树)。渲染没有副作用(例如DOM不会 更新)。
答案 1 :(得分:3)
即使我想知道为什么我的控件渲染两次。
我的大多数组件中都没有useEffect挂钩,并且大多数情况下,我只是在用户在输入框中输入数据时设置状态(不可变)。在具有两个为什么绑定的每个组件中也会发生这种情况。
DevTools: 我在没有安装devtools的浏览器中尝试了我的应用程序,仍然存在相同的问题。
React.StrictMode 我认为这是潜在的罪魁祸首。当我从index.js删除此标签时,所有组件都开始正常工作。 我还阅读了官方文档,其中strictMode检查仅在开发人员模式下执行,而在生产版本中将被忽略。
这使我认为我们的代码是正确的,我们可以忽略开发人员中的重新渲染问题。
答案 2 :(得分:2)
您的“ setSearch”正在更新输入框的名称,然后您的“ useEffect”会在搜索更改时再次对其进行更新。
删除useEffect
然后
const handleSearch = (event) => {
setSearch(event.target.value);
localStorage.setItem('search', event.target.value)
}
这是一个沙盒链接:https://codesandbox.io/s/dawn-night-h2xiz?file=/src/App.js
它确实不能解决问题,但将来可能会避免一些问题。
双重渲染只能在开发模式下进行,而不能在生产环境下进行。请在此处查看Dan Abramov的回复: https://github.com/facebook/react/issues/15074
答案 3 :(得分:0)
我同意@denislexic,这是解决此问题的一种方法。
代替
useEffect(() => {
localStorage.setItem('search', search);
}, [search]);
const handleSearch = (event) => {
setSearch(event.target.value);
};
让我们执行以下操作:
const handleSearch = (event) => {
const search = event.target.value;
setSearch(search);
localStorage.setItem('search', search);
};
这将在一个例程中而不是2个例程中完成相同的2个任务(保存到状态和本地存储)。 提示:useEffect会导致重新渲染
希望有帮助。
干杯! ?