I have right here a component that should simply render a list of items. Also, the component includes an input that filters the list of items. If there is no items, or if the items are being loaded it should display a message.
import { useState } from "react";
export const List = ({ loading, options }) => {
const _options = options ?? [];
const [renderedOptions, setRenderedOptions] = useState(_options);
const [inputValue, setInputValue] = useState("");
function handleChange(event) {
setInputValue(event.target.value);
const filteredOptions = _options.filter((option) =>
option.toLowerCase().includes(event.target.value.toLowerCase())
);
setRenderedOptions(filteredOptions);
}
return (
<div>
<input type="text" value={inputValue} onChange={handleChange} />
<ul>
{renderedOptions.length > 0 ? (
renderedOptions.map((option) => <li key={option}>{option}</li>)
) : loading ? (
<li>Loading...</li>
) : (
<li>Nothing to show</li>
)}
</ul>
</div>
);
};
In App.js, I did a setTimeout, to mock a fetch call. However, there is a problem. Although I'm setting the asyncOptions state to be the new list of items, in my <List /> component the options do not seem to display properly.
import { List } from "./List";
import { useState, useEffect } from "react";
const ITEMS = ["list_1", "list_2", "list_3", "list_4", "list_5"];
export default function App() {
const [asyncOptions, setAsyncOptions] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
const timeoutId = setTimeout(() => {
setIsLoading(false);
setAsyncOptions(ITEMS);
}, 2000);
return () => clearTimeout(timeoutId);
}, []);
return <List options={asyncOptions} loading={isLoading} />;
}
What is this happening and what is/are the solution(s)?
Sandbox code here: https://codesandbox.io/s/async-list-j97u32