I did a simple crud that consume a API with useEffect
, but the problem appears when go to other page (no in my application, I've only one page) and back to my page.
Example:
I've these values and change to:
When I go to other page and back this page, the values appears like in first image.
Context file:
function loadApi(){
fetch("http://localhost:8000/get-names")
.then(response => response.json())
.then(data => {setItems(data);console.log(data)})
}
useEffect(() => loadApi(),[])
const [items,setItems] = useState<ItemType[] | undefined>()
console.log("Items: "+ JSON.stringify(items))
const addItem = async (name: string) => {
const response = await fetch("http://localhost:8000/insert-name",{
method: "POST",
body: JSON.stringify({name: name}),
headers: {"content-type": "application/json"},
})
const data: ItemType = await response.json()
if (items) setItems([...items,data])
else setItems([data])
}
const removeItem = async (item: ItemType) => {
const response = await fetch("http://localhost:8000/remove-name",{
method: "DELETE",
body: JSON.stringify({
name: item.name,
id: item.id
}),
headers: {"content-type": "application/json"},
})
const data: ItemType = await response.json()
const newArray = items?.filter(el => el.id != item.id)
setItems(newArray)
}
const editItem = async (name: string,item: ItemType) => {
const response = await fetch("http://localhost:8000/update-name",{
method: 'PUT',
body: JSON.stringify({
id: item.id,
name: item.name,
newName: name,
}),
headers: {"content-type": "application/json"}
})
const data = await response.json()
const newArray = items?.map(el => {
el.name = el.id == item.id ? name : item.name;
return el
})
setItems(newArray)
}
return(
<ItemsContext.Provider value={{items,addItem,removeItem,editItem}}>
{children}
</ItemsContext.Provider>
)
App.tsx
const [search, setSearch] = useState<string>("")
const [addInput, setAddInput] = useState<string>("")
const context = useContext(ItemsContext)
const addItems = () => {
if(addInput != ""){
context?.addItem(addInput)
setAddInput("")
}
}
//@ts-ignore
const enterKey = (e) => {
if (e.key === 'Enter') {
addItems()
}
}
return (
<main>
<nav>
<input
id='searchInput'
type="text"
value={search}
onChange={e => setSearch(e.target.value)}
/>
<FaSearch className="inputButton" />
</nav>
<section id='cardBox'>
{context && context?.items?.map((item: ItemType) => {
if (item.name.toLowerCase().includes(search.toLowerCase()) || search == ""){
return <Card key={item.id} name={item.name} id={item.id}/>
}
})}
</section>
<div id='inputFooter'>
<input
id='addInput'
type="text"
value={addInput}
onChange={e => setAddInput(e.target.value)}
onKeyDown={enterKey}
/>
<IoIosAddCircle className="inputButton" onClick={() => addItems()}/>
</div>
</main>
)
How see in code, the console shows "item" and "data", but they has the first image value even after updating and coming back to page, but when reload page back to normal and consume the updated values.
Each time you call an API to modify your data on the backend, you need to call loadApi()
to update the state with the new data from the db.
For instance:
const removeItem = async (item: ItemType) => {
const response = await fetch("http://localhost:8000/remove-name",{
method: "DELETE",
body: JSON.stringify({
name: item.name,
id: item.id
}),
headers: {"content-type": "application/json"},
})
const data: ItemType = await response.json()
const newArray = items?.filter(el => el.id != item.id)
setItems(newArray);
loadApi();
}
const editItem = async (name: string,item: ItemType) => {
const response = await fetch("http://localhost:8000/update-name",{
method: 'PUT',
body: JSON.stringify({
id: item.id,
name: item.name,
newName: name,
}),
headers: {"content-type": "application/json"}
})
const data = await response.json()
const newArray = items?.map(el => {
el.name = el.id == item.id ? name : item.name;
return el
})
setItems(newArray);
loadApi();
}