当使用字符串setString("some string")
设置useStateconst [searchString, setString] = useState([])
时,它将立即发送并显示在另一个组件<Home/>
,
BUT当我发送数组时,它只会在此处的第二个onClick
之后声明为settingResults(resultArray)
我试过settingResults([...resultArray])
,还是一样。
使用console.log()
检查所有功能。
页眉.jsx
function Header({ settingResults }) {
const [productsObj, setObjs] = useState([]);
const [searchString, setString] = useState('');
let resultArray = [];
const onChangHandler = (e) => {
setString(e.target.value);
};
const activeSearch = () => {
if (searchString.length > 0) {
resultArray = productsObj.filter((obj) =>
obj.productName.toLowerCase().includes(searchString.toLowerCase())
);
if (resultArray.length !== 0) {
settingResults(resultArray);
}
}
resultArray = [];
};
return (
<div>
<header className='header-shop'>
Welcome to Vitamins Store
<br />
<input
placeholder='Search here'
value={searchString}
onChange={(e) => onChangHandler(e)}
/>
<button onClick={activeSearch}>Search</button>
</header>
</div>
);
}
App.js
function App() {
const [searchString, setString] = useState([]);
return (
<div className='App'>
<Header settingResults={setString} />
<Home searchResults={searchString} />
<Footer />
</div>
);
}
主页.jsx
function Home({ searchResults }) {
const [itemSearchResults, setResults] = useState([]);
const [viewResults, setViewResult] = useState(null);
let itemsFound = [];
useEffect(() => {
setResults(searchResults);
itemsFound = itemSearchResults.map((productObj) => {
return (
<div key={productObj.id}>
{productObj.productName} <br />
{productObj.price}
<br />
<img src={productObj.image} />
</div>
);
});
setViewResult(itemsFound);
}, [searchResults]);
return (
<div>
<h3>Home</h3>
<h1>{viewResults}</h1>
</div>
);
}
有人知道为什么useState
第一次不能使用对象数组吗
代码的问题在于以下两行:
setResults(searchResults);
itemsFound = itemSearchResults...
调用setResults
不会立即改变itemSearchResults
。相反,它会将要在当前渲染之后进行的更改排队。但在searchResults
再次更改之前,不会再次调用此代码。
为什么要使用itemSearchResults
?看起来你可以只使用searchResults
,就像下面的最小变化:(但请参阅下面的更好的答案(
function Home({ searchResults }) {
const [viewResults, setViewResult] = useState(null);
useEffect(() => {
const itemsFound = searchResults.map((productObj) => {
return (
<div key={productObj.id}>
{productObj.productName} <br />
{productObj.price}
<br />
<img src={productObj.image} />
</div>
);
});
setViewResult(itemsFound);
}, [searchResults]);
return (
<div>
<h3>Home</h3>
<h1>{viewResults}</h1>
</div>
);
}
使用useMemo
:也可以更好地编写此代码
function Home({ searchResults }) {
const viewResults = useMemo(() => {
return searchResults.map((productObj) => {
return (
<div key={productObj.id}>
{productObj.productName} <br />
{productObj.price}
<br />
<img src={productObj.image} />
</div>
);
});
}, [searchResults]);
return (
<div>
<h3>Home</h3>
<h1>{viewResults}</h1>
</div>
);
}
正如评论中所指出的,以这种方式记忆是危险的,你最好直接这样呈现:
function Home({ searchResults }) {
return (
<div>
<h3>Home</h3>
<h1>
{searchResults.map((productObj) =>
<div key={productObj.id}>
{productObj.productName} <br />
{productObj.price}
<br />
<img src={productObj.image} />
</div>
)}
</h1>
</div>
);
}
// This will guarantee re-rendering only when the props change.
Memo = React.memo(Memo);