【问题标题】:React Hook [useState]: update state and rerender the viewReact Hook [useState]:更新状态并重新渲染视图
【发布时间】:2019-12-24 07:43:11
【问题描述】:

经验:我是 React 的初学者。

我要学习的内容: Hooks (useState) - 但我不知道如何更新状态并以此重新渲染视图。据我了解,如果更新后的状态与上一个有点相似,React 不会重新渲染视图......在谷歌搜索之后,我尝试复制状态并以某种方式更新它,但我遗漏了一些东西,我不知道什么。

我想在项目中做什么:当用户从下拉列表中选择一个地区时,我有一个我想要过滤的国家/地区列表。这是在选择发生时触发的函数,以及我希望解释我想要做什么的 cmets:

    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);
    };

您可以找到相关文件和代码HERE(向下滚动以访问change 函数)

  1. 从“按地区过滤器”下拉菜单中选择一个地区

  2. 在控制台中查看错误/输出

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    您正在将状态更新为对象数组,最后一项将是过滤后的列表

    相反,传入一个包含过滤国家/地区的数组。

    请注意,当您第二次选择不同的地区时,您的状态将丢失,因为您正在修改整个国家/地区集合。

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

    那么我们能做些什么来避免丢失状态呢?

    我们可以根据所选区域过滤列表。

    在我更改代码的地方添加了 cmets

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      相关资源
      最近更新 更多