簡體   English   中英

反應 useState 鈎子沒有正確更新

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM