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}
