排序和过滤 React - 上下文

IT技术 reactjs
2021-05-23 00:20:28

我做了一些研究,但我发现旧的例子通常是 Redux 或一个主要组件,但无法弄清楚逻辑。

我可以从 API 获取数据,但我确实需要对该数据进行搜索、排序、过滤等(即使是同时进行)。我知道我不应该直接改变状态,所以在这种情况下,我将有几个不同的状态集,例如filteredData、sortedData 等。但是,我将把哪个状态传递给 Player 组件?排序功能将如何处理过滤后的数据?我非常困惑。

我想将我的状态和与状态相关的逻辑放在 Context 中,但如果这看起来有问题或错误,那么我可以尝试您的方法。

语境

const ContextProvider = ({ children }) => {

  const [data, setData] = useState([]);
  const [filteredData, setFilteredData] = useState([]);
  const [sortedData, setSortedData] = useState([]);

  useEffect(() => {
    fetch('URL HERE')
      .then(data => data.json())
      .then(data=> setData(data));
  }, []);

  const handleSearch = e => {
    let value = e.target.value;
    const filteredData = data.filter(player=>
        player.name.includes(value)
    );
    setFilteredData(filteredData);
  };

  const handleSort = e => {
    let value = e.target.value;
    // I am trying to sort FILTERED DATA?
    const sortedData = filteredData.sort((a, b) => {
      if (a[value] < b[value]) {
        return 1;
      } else {
        return -1;
      }
    });
    setSortedData(sortedData);
  };

  return (
    <Context.Provider
      value={{ data, handleSearch, handleSort, filteredData, sortedData}}
    >
      {children}
    </Context.Provider>
  );
};

搜索

const Search = () => {

  const { handleSearch, handleSort } = useContext(Context);
  return (
    <div className='row'>
      <Input
        type='search'
        name='search'
        onChange={handleSearch}
      ></Input>
      <Input
        type='select'
        name='select'
        onChange={handleSort}
      >
        <option value='name'>Name</option>
        <option value='team'>Team</option>
      </Input>
    </div>
  );
};

播放器

const Player = () => {
  const {data, filteredData, sortedData} = useContext(Context);
  return (
      <ul>
        //{data or filteredData or sortedData will be mapped?}
        <li>// not sure what to do</li>
      </ul>
  );
};

我真的很欣赏带有一些解释的代码示例。

1个回答

有很多方法可以做到这一点。

我的建议是:-

  1. 设置const [filteredData, setFilteredData] = useState(data) (这将不起作用)所以useEffect()filteredDataPlayer那时更新:-
useEffect(() => {
  setFilteredData(data)
}, [])
  1. 在用户提出的每个请求(输入)上,将被更新 setFilteredData()
  • 如果用户对 不做任何操作inputs,则返回filteredData包含 dafault 的内容data
  • 如果用户search输入,然后filtering搜索filteredData(使用setFilteredData()
  • 如果用户sort输入,然后sorting继续filteredData(使用setFilteredData()
  • 如果用户同时执行searchsort输入,则对filteredData(使用setFilteredData()执行这两个操作
  1. Player,你可以return filteredData

语境

const ContextProvider = ({ children }) => {

  const [data, setData] = useState([]);
  const [filteredData, setFilteredData] = useState([]);
  const [searchKey, setSearchKey] = useState('');
  const [sortKey, setSortKey] = useState([]);

  useEffect(() => {
    fetch('URL HERE')
      .then(data => data.json())
      .then(data=> setData(data));
  }, []);

  const handleSearch = () => {
    const filteredData = filteredData.filter(player=>
        player.name.includes(searchKey)
    );
    setFilteredData(filteredData);
  };

  const handleSort = () => {
    const sortedData = filteredData.sort((a, b) => {
      if (a[sortKey] < b[sortKey]) {
        return 1;
      } else {
        return -1;
      }
    });
    setFilteredData(sortedData);
  };

  return (
    <Context.Provider
      value={{
        data, filteredData, searchKey, sortKey,
        setFilteredData, setSearchKey, setSortKey,
        handleSearch, 
        handleSort, 
      }}
    >
      {children}
    </Context.Provider>
  );
};

搜索

const Search = () => {

  const {
    searchKey, setSearchKey,
    sortKey, setSortKey
  } = useContext(Context);
  
  return (
    <div className='row'>
      <Input
        type='search'
        name='search'
        value={searchKey}
        onChange={e => setSearchKey(e.target.value)}
      ></Input>
      <Input
        type='select'
        name='select'
        value={sortKey}
        onChange={e => setSortKey(e.target.value)}
      >
        <option value='name'>Name</option>
        <option value='team'>Team</option>
      </Input>
    </div>
  );
};

播放器

const Player = () => {
  const {
    data,
    filteredData, setFilteredData,
    searchKey, sortKey.
    handleSearch, handleSort
  } = useContext(Context);
 
  // set filteredData
  useEffect(() => {
    setFIlteredData(data)
  }, []) // should run once on mounted

  // do search
  // should be dependent on search input state (so you need a state to hold value need for searching)
  useEffect(() => {
    handleSearch()
  }, [searchKey]) // will only fired/run if searchState changes

  // do sorting
  // should be dependent on sorting input state (so you need a state to hold value need for sorting)
  useEffect(() => {
    handleSort()
  }, [sortKey]) // will only fired/run if sortingState changes

  return (
      <ul>
        {filteredData.map(data => (
          {/* display data info */}
        ))}
      </ul>
  );
};