簡體   English   中英

React Hook [useState]:更新狀態並重新渲染視圖

[英]React Hook [useState]: update state and rerender the view

經驗:我是 React 的初學者。

我正在嘗試學習: Hooks ( useState ) - 但我不知道如何更新狀態並用它重新渲染視圖。 據我了解,如果更新的狀態與上一個有點相似,React 不會重新渲染視圖......谷歌搜索后,我嘗試復制狀態並以某種方式更新它,但我錯過了一些東西,我不知道什么。

我在項目中嘗試做的事情:當用戶從下拉列表中選擇一個區域時,我有一個要過濾的國家/地區列表。 這是在選擇發生時被觸發的函數,以及我希望解釋我想要做什么的評論:

    const change = event => {
        //copy the `data` state (which has a list of all the countries)
        let newData = [...data];
        console.log(newData);

        //filter through the countries list to get only those with the selected region
        let filtered = newData.filter(obj => obj.region === event.target.value);
        console.log(filtered);

        //change the countries list with the filtered one, and rerender the view
        setData([data, newData]);
        console.log(data);
    };

您可以在此處找到相關文件和代碼(向下滾動以訪問change功能)

  1. 從“按區域篩選器”下拉列表中選擇一個區域

  2. 查看控制台中的錯誤/輸出

您正在將狀態更新為一組對象,最后一項將是過濾后的列表

相反,傳入一個包含過濾國家/地區的數組。

請注意,第二次選擇不同的地區時,您的狀態將丟失,因為您正在修改整個國家/地區集合。

setData(data.filter(obj => obj.region === event.target.value))

那么我們怎樣才能避免失去狀態呢?

我們可以根據所選區域過濾列表。

添加了我更改代碼的注釋

export default function CountriesList() {
  const [data, setData] = useState([]);
  const [distinctRegions, setDistinctRegions] = useState([]);
  const [loading, setLoading] = useState(true);
  // added state to track the selected region
  const [selectedRegion, setSelectedRegion] = useState("");

  useEffect(() => {
    CountriesAPI().then(res => {
      onLoad(res);
      setLoading(false);
    });
  }, []);

  const onLoad = dataList => {
    setData(...data, dataList);
    getRegions(dataList);
  };

  const getRegions = dataList => {
    let regions = [];

    dataList.map(dataItem =>
      dataItem.region.length ? regions.push(dataItem.region) : ""
    );

    let regionsFiltered = regions.filter(
      (item, index, arr) => arr.indexOf(item) === index
    );

    setDistinctRegions(...distinctRegions, regionsFiltered);
  };

  const renderLoading = () => {
    return <div>Loading...</div>;
  };

  // now we only need to update the selected region
  const change = event => {
    setSelectedRegion(event.target.value);
  };

  const renderData = (dataList, distinctRegionsItem) => {
    if (dataList && dataList.length) {
      return (
        <div>
          <Container>
            <Input type="text" placeholder="Search for a country..." />
            <Select className="select-region" onChange={change}>
              <option value="" hidden>
                Filter by region
              </option>
              // added show all
              <option value="">Show All</option>
              {distinctRegionsItem.map(item => {
                return (
                  <option key={item} value={item}>
                    {item}
                  </option>
                );
              })}
            </Select>
          </Container>
          <CardList>
            // filter the array based on selectedRegion and then render the list.
            // if selectedRegion is empty show all
            {dataList
              .filter(
                country => !selectedRegion || country.region === selectedRegion
              )
              .map(country => (
                <CountryCard
                  population={country.population}
                  region={country.region}
                  capital={country.capital}
                  flag={country.flag}
                  key={country.alpha3Code}
                  id={country.alpha3Code}
                  name={country.name}
                />
              ))}
          </CardList>
        </div>
      );
    } else {
      return <div>No items found</div>;
    }
  };

  return loading ? renderLoading() : renderData(data, distinctRegions);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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