useState只在第二个onClick中发送道具,而在第一个onClick中有一个字符串,为什么



当使用字符串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);

最新更新