[英]React useState hook not updating correctly
我是學習 React 的初學者,遇到了一個我無法弄清楚的問題。 基本上我有一個從列表中過濾掉結果的輸入字段,並且應該根據輸入的過濾器呈現不同的列表。問題是當過濾和呈現結果時,基本上是輸入值的最后一個字母被忽略。 下面的例子。
如果我輸入字符“s”,什么也不會發生: Image 。 相反應該發生的是段落標簽應該使用內容“匹配太多,指定另一個過濾器”來呈現。
然后,如果我輸入字母“w”,它會呈現之前應該呈現的段落標簽: Image 。 相反,應該呈現的是名稱包含 substring“sw”的國家/地區列表。
然后,如果我輸入字母“e”,它會呈現在我輸入前一個字符時應該呈現的列表: Image 。 如您所見,列表中的國家名稱包含 substring “sw”,基本上忽略了輸入的最后一個字符。
我的代碼:
主要應用組件:
import axios from "axios";
import Filter from "./Filter";
import "./styles.css";
import Content from "./Content";
const App = () => {
const [countries, setCountries] = useState([])
const [allCountries, setAllCountries] = useState([])
const [newFilter, setNewFilter] = useState("")
useEffect(() => {
axios
.get('https://restcountries.com/v3.1/all')
.then(response => {
setAllCountries(response.data)
})
}, [])
const handleFilterChange = (event) => {
setNewFilter(event.target.value);
if (newFilter) {
const regex = new RegExp(newFilter, "i");
const filteredCountries = () => allCountries.filter(country => country.name.common.match(regex));
setCountries(filteredCountries)
}
}
return (
<div>
<Filter value={newFilter} onChange={handleFilterChange} />
<Content countries={countries} setCountries={setCountries} />
</div>
)
}
export default App
過濾器(輸入字段)組件:
import React from "react";
const Filter = (props) => {
return (
<input value={props.value} onChange={props.onChange} />
);
}
export default Filter;
內容組件:
import React from "react";
const Content = ({countries, setCountries}) =>{
if (countries.length > 10){
return <p>Too many matches, specify another filter</p>;
} else if ((countries.length > 2 && countries.length < 10) || countries.length === 0){
return <ul>{countries.map((country, i) => <li key={i}>{country.name.common}</li>)}</ul>;
} else {
return <p>{countries[0].name.common}</p>;
}
}
export default Content;
幫助將不勝感激!
你的問題在這里:
const handleFilterChange = (event) => {
setNewFilter(event.target.value);
if (newFilter) {
const regex = new RegExp(newFilter, "i");
const filteredCountries = () => allCountries.filter(country => country.name.common.match(regex));
setCountries(filteredCountries)
}
}
具體來說:
if (newFilter)
您需要將其更改為:
if( event.target.value) ...
setNewFilter
不會更新您的本地state 變量,因為在 React 中,state 是不可變的。
所以你的if語句在這里:
const handleFilterChange = (event) => {
setNewFilter(event.target.value);
if (newFilter) {
...
}
}
第一次將評估為假。
只需更改為
const handleFilterChange = (event) => {
setNewFilter(event.target.value);
if (event.target.value) {
...
}
}
引用 state 變量只會為您提供上次調用useState
的值,即。 在這一行:
const [newFilter, setNewFilter] = useState("")
局部變量newFilter
直到組件下次渲染時才會更新,因為useState
將再次被調用。
import "./styles.css";
import Content from "./Content";
const App = () => {
const [countries, setCountries] = useState([])
const [allCountries, setAllCountries] = useState([])
const [newFilter, setNewFilter] = useState("")
useEffect(() => {
axios
.get('https://restcountries.com/v3.1/all')
.then(response => {
setAllCountries(response.data)
})
}, [])
const handleFilterChange = (event) => {
setNewFilter(event.target.value);
if (newFilter) { // at this point, the newFilter is not set as a new value yet. So you'd better to use event.target.value instead of newFilter.
const regex = new RegExp(newFilter, "i");
const filteredCountries = () => allCountries.filter(country => country.name.common.match(regex));
setCountries(filteredCountries)
}
}
return (
<div>
<Filter value={newFilter} onChange={handleFilterChange} />
<Content countries={countries} setCountries={setCountries} />
</div>
)
}
export default App
或者你可以使用useEffect
鈎子。
import "./styles.css";
import Content from "./Content";
const App = () => {
const [countries, setCountries] = useState([])
const [allCountries, setAllCountries] = useState([])
const [newFilter, setNewFilter] = useState("")
useEffect(() => {
axios
.get('https://restcountries.com/v3.1/all')
.then(response => {
setAllCountries(response.data)
})
}, [])
useEffect(() => {
if (newFilter) {
const regex = new RegExp(newFilter, "i");
const filteredCountries = () => allCountries.filter(country => country.name.common.match(regex));
setCountries(filteredCountries)
}
}, [newFilter])
const handleFilterChange = (event) => {
setNewFilter(event.target.value);
}
return (
<div>
<Filter value={newFilter} onChange={handleFilterChange} />
<Content countries={countries} setCountries={setCountries} />
</div>
)
}
export default App
希望這對您有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.