Home > OS >  onChange antd Input component doesn't setState (hook) properly with list from axios get in Reac
onChange antd Input component doesn't setState (hook) properly with list from axios get in Reac

Time:01-27

I'm new to React, been working on it for the past week. I'm trying to make a simple app that has a 'product create' form and a list of products with a search bar (using Input component from antd); in the list I can click on any product to open the details page.

Right now I'm blocked by some not properly working logic or something I miss. When I tried the Input onChange with an Array I created in the code it worked fine, but now that I'm using a mock api (from fakestoreapi.com to be precise), I can't make it work.

ProductsList.tsx

function ProductsList() {
  const [list, setList] = useState<Array<Product>>([]);
  const [loading, setLoading] = useState<boolean>(true);

  useEffect(() => {   // I think something is wrong here
    ProductService.getAll()
      .then((res: any) => {
        setList(res.data);
        setLoading(false);
      })
      .catch((e: Error) => console.log(e));
  }, []);  // tried: 'query' const from state, 'filterList' from state 
  
  function onChange(e: React.ChangeEvent<HTMLInputElement>) {   // Or here (or both here and in useEffect)
    console.log('in onChange');
    const filterList: Array<Product> = list.filter((item) =>
      item.title.toLowerCase().startsWith(e.target.value.toLowerCase())
    );
    setList(filterList);
  }

  return (
    <div>
      <Spin spinning={loading}>
        <List
          header={
            <Input
              type="text"
              placeholder="Search product"
              allowClear
              onChange={onChange}
            />
          }
          split
          dataSource={list}
          renderItem={(item) => (
            <List.Item key={item.id}>
              <Link to={`/products/${item.id}`}>{item.title}</Link>
            </List.Item>
          )}
        ></List>
      </Spin>
    </div>
  );
}

export default ProductsList;

I tried adding some dependencies to the useEffect hook, but maybe they were the wrong ones. As I said, with a local array this worked, but now after loading the full list once, when I get to the Input and search something, the list is deleted. I think I spotted the problem in the fact that I don't reset the list to the full one, but I don't actually know how to do that (that's why I'm here). I tried to search something online but except for dependencies, I didn't find something specific to help me.

If needed, here is the ProductService.getAll() function:

function getAll() {   // http is axios
    return http.get<Array<Product>>(`/products`);
}

I'll be glad to add everything that could be helpful if needed.

CodePudding user response:

const [list, setList] = useState<Array<Product>>([]); // The full list
const [filteredList, setFilteredList] = useState<Array<Product>>([]); // the list you display

  function onChange(e: React.ChangeEvent<HTMLInputElement>) {   // Or here (or both here and in useEffect)
    console.log('in onChange');
    const temp: Array<Product> = list.filter((item) => //keep the filter on the full list but only display the filtered list
      item.title.toLowerCase().startsWith(e.target.value.toLowerCase())
    );
    setFilteredList(temp);
  }
//the datasource: dataSource={filteredList}
  •  Tags:  
  • Related