hello i'm trying to delete my rows through states and axios request but i'm not sure how can i manage my api data through states, i have to update my table when i delete the row, right now if i log states dont have data to manage
import React, {useMemo} from 'react';
import {useSortBy, useTable, usePagination} from 'react-table';
import apiData from '../../../modules/searchCards/apiHooks/apiData.js';
import DeleteModal from '../../../DeleteModal/index.jsx';
import axios from 'axios';
/* eslint-disable react/prop-types */
const useTableResource = () => {
const {data} = apiData();
const resourcesData = data;
const resourcesDataLength = resourcesData.length;
// i try to convert my data into useState but is not working i'm not sure why
const [datas, setData] = React.useState(React.useMemo(() => data, []));
const resourcesColumns = useMemo(() => [
{
id: 'delete',
accessor: () => 'delete',
disableSortBy: true,
Cell: ({row}) => <div onClick={(event) => event.stopPropagation()} style={{
display: 'flex',
justifyContent: 'center'
}}>
<DeleteModal delb={async (index) => {
// here should update my data state when i delete
setData(datas.filter((item, i) => i !== index));
await axios.delete(`api/resources?_id=${row.original._id}`);
}}/>
</div>
}
], []);
const tableInstance = useTable({
columns: resourcesColumns,
data: resourcesData,
disableSortRemove: true,
}, useSortBy, usePagination);
return {
tableInstance,
resourcesColumns,
resourcesDataLength
};
};
export default useTableResource;
There's a lot going on in the code that's probably not relevant to the question, sounds like the main issue is nothing is being returned once you've deleted a record/item.
Try something like this:
const [data, setData] = useState({});
function getData() {
axios.get("https://api.example.com")
.then((response) => response.json())
.then((data) => setData(data));
}
function deleteItem(id) {
axios.delete("https://api.example.com/" + id)
.then(() => getData());
}
In this way, after the item has been deleted, you're then calling the api to get the latest update.
In another scenario, it's possible your delete api call is returning the new updated records already, in which case:
function deleteItem(id) {
axios.delete("https://api.example.com/" + id)
.then((response) => response.json())
.then((data) => setData(data));
}
Again using example code, but you should be able to go from there.
Related
having an issue, when the when nav to the comp the items state is empty, if I edit the code and page refreshes its shows up and if I add the state to the useEffect "[itemCollectionRef, items]" it's an inf loop but the data is their anyone have a better idea or way to fetch the data for display from firestore.
import React, { useState, useEffect } from "react";
import { Grid, Box, Button, Space } from "#mantine/core";
import { ItemBadge } from "../../components/NFAItemBadge";
import { useNavigate } from "react-router-dom";
import { db, auth } from "../../firebase";
import { getFirestore, query, getDocs, collection, where, addDoc } from "firebase/firestore";
import { useAuthState } from "react-firebase-hooks/auth";
const ItemTrack = () => {
const [user, loading, error] = useAuthState(auth);
const navigate = useNavigate();
const [items, setItems] = useState([]);
const itemCollectionRef = collection(db, "items");
useEffect(() => {
//if(!user) return navigate('/');
//if(loading) return;
const q = query(itemCollectionRef, where("uid", "==", user.uid));
const getItems = async () => {
const data = await getDocs(q);
setItems(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
console.log("Fetched Items: ", items);
};
getItems();
}, []);
if (loading) {
return (
<div>
<p>Initialising User....</p>
</div>
);
}
if (error) {
return (
<div>
<p>Error: {error}</p>
</div>
);
}
if (user) {
return (
<Box sx={{ maxWidth: 1000 }} mx="auto">
</Box>
);
} else {
return navigate("/");
}
};
export default ItemTrack;
It will depend how you will render the data from the useEffect. setState does not make changes directly to the state object. It just creates queues for React core to update the state object of a React component. If you add the state to the useEffect, it compares the two objects, and since they have a different reference, it once again fetches the items and sets the new items object to the state. The state updates then triggers a re-render in the component. And on, and on, and on...
As I stated above, it will depend on how you want to show your data. If you just want to log your data into your console then you must use a temporary variable rather than using setState:
useEffect(() => {
const newItems = data.docs.map((doc) => ({ ...doc.data(), id: doc.id }))
console.log(newItems)
// setItems(newItems)
}, [])
You could also use multiple useEffect to get the updated state object:
useEffect(() => {
setItems(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })))
}, [])
useEffect(() => { console.log(items) }, [items])
If you now want to render it to the component then you have to call the state in the component and map the data into it. Take a look at the sample code below:
useEffect(() => {
const q = query(itemCollectionRef, where("uid", "==", user.uid));
const getItems = async () => {
const data = await getDocs(q);
setItems(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
getItems();
}, []);
return (
<div>
<p>SomeData: <p/>
{items.map((item) => (
<p key={item.id}>{item.fieldname}</p>
))}
</div>
);
I have this endpoint to get basic data for my app:
https://app.subsocial.network/subid/api/v1/chains/properties
In the response i have an object like this:
{
"edgeware": {
"ss58Format": 7,
"tokenDecimals": [
18
],
"tokenSymbol": [
"EDG"
],
"icon": "edgeware-circle.svg",
"name": "Edgeware"
},
"chainx": {
"icon": "chainx.svg",
"name": "ChainX"
},
What I need is to display name and icon for each particular object (for example in this case for the first instance it will be like this by mapping the main object:
the name we can get like that: {item.name}
and the icons we can get like this: <img src={https://app.subsocial.network/subid/icons/${item.icon}}/>
).
BUT! Near each particular item I also need a status of a request, that was made to a particular url, based on each object. For example for the first object it will be https://app.subsocial.network/subid/api/v1/check/edgeware. This request is returning a boolean value and i just want to display it near the name and icon.
For now I have this code, and i cant figure out how to make second request and to display it. Besides, I need to update all the statuses every 5 minutes. I trying this, but I have all true or all false values, despite that API is work correct.
import React, { useState, useEffect } from 'react';
import { ImageContainer, IconImage, ItemWrapper, RedSquare, GreenSquare, ItemName, LoadingWrapper } from './styled-containers';
function App() {
const [data, setData] = useState([]);
const [finalData, setFinalData] = useState([]);
const [loading, setLoading] = useState(true);
const transformData = (obj, statuses) => {
const array = [];
for (let key in obj) {
array.push({ ...obj[key], statuses: statuses });
}
return array
}
const fetchData = () => {
fetch('https://app.subsocial.network/subid/api/v1/chains/properties')
.then(response => response.json())
.then(data => setData(data))
.catch(error => console.log(error))
}
useEffect(() => {
fetchData()
}, []);
useEffect(() => {
for (let key in data) {
fetch(`https://app.subsocial.network/subid/api/v1/check/${key}`)
.then(response => response.json())
.then(itemStatus => setFinalData(transformData(data, itemStatus)))
.catch(error => console.log(error))
.finally(setLoading(false))
}
setInterval(() => {
fetchData()
}, 30000)
}, [data])
console.log(finalData)
return (
<div className="App">
{loading ? <LoadingWrapper>...loading</LoadingWrapper> : finalData.map((item, index) => {
return (
<ItemWrapper key={index}>
<ImageContainer >
<IconImage src={`https://app.subsocial.network/subid/icons/${item.icon}`} alt='' />
</ImageContainer>
<ItemName>{item.name}</ItemName>
{finalData.statuses ? <GreenSquare /> : <RedSquare />}
</ItemWrapper>
)
})}
</div>
);
}
export default App;
I was trying to fetch api with react.js but on first render its gives nothing and the second render its gives data. This makes it so when I try to access the data later for an image I get an error, TypeError: Cannot read property 'news.article' of undefined, because it is initially empty. how can I solve this?
here is my code ..
import React, { useEffect, useState } from 'react';
const HomeContent = () => {
const [news, updateNews] = useState([]);
console.log(news);
useEffect(() => {
const api = 'http://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=940c56bd75da495592edd812cce82149'
fetch(api)
.then(response => response.json())
.then(data => updateNews(data))
.catch((error) => console.log(error))
}, [])
return (
<>
</>
);
};
export default HomeContent;
There is no issue with the code itself, the output you receive is expected. However, you can render the content after it is retrieved as such
import React, { useEffect, useState } from 'react';
const HomeContent = () => {
const [news, updateNews] = useState([]);
const [isLoading, setIsLoading] = useState(true);
console.log(news);
useEffect(() => {
const api = 'http://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=940c56bd75da495592edd812cce82149'
fetch(api)
.then(response => response.json())
.then(data => {
updateNews(data.articles);
setIsLoading(false);
})
.catch((error) => {
console.log(error);
setIsLoading(false);
})
}, [])
return (
<>
{isLoading ?
<p>Loading...</p> :
// Some JSX rendering the data
}
</>
);
};
export default HomeContent;
I am trying to get data from my firebase-firestore I an showing a loading state to wait for the data to load however when it does load it keeps returning the firestore data infinite times. Please may someone help me.
This is my code Paper is just a custom component
import Paper from '../Components/Paper'
import firebase from 'firebase'
import { useState } from 'react'
const Home = (props) => {
const renderMealItem = (itemData) =>{
return (
<Paper
title={itemData.item.name}
serves={itemData.item.servings}
time={itemData.item.time}
image={itemData.item.imageUri}
/>
)
}
const [loading, setLoading] = useState(false)
const [all, setAll] = useState([])
useEffect(() => {
setLoading(true)
checkReturn()
getUser()
},[])
const checkReturn = () => {
if(all !== undefined){
setLoading(false)
}
}
const getUser = async() => {
try {
await firebase.firestore()
.collection('Home')
.get()
.then(querySnapshot => {
querySnapshot.docs.forEach(doc => {
setAll(JSON.stringify(doc.data()));
});
});
}catch(err){
console.log(err)
}
}
return(
<View style={styles.flatContainer}>
<FlatList
data={all}
keyExtractor={(item, index) => index.toString()}
renderItem={renderMealItem}/>
</View>
)
}
useEffect without second parameter will get executes on each update.
useEffect(() => {
setLoading(true)
checkReturn()
getUser()
})
so this will set the loading and tries to get the user. and when the data comess from server, it will get runned again.
So you should change it to : useEffect(() => {...}, []) to only get executed on mount phase(start).
Update: you should check for return on every update, not only at start. so change the code to:
useEffect(() => {
setLoading(true)
getUser()
}, [])
useEffect(() => {
checkReturn()
})
Ps: there is another issue with your code as well:
querySnapshot.docs.forEach(doc => {
setAll(JSON.stringify(doc.data()));
});
maybe it should be like :
setAll(querySnapshot.docs.map(doc => JSON.stringify(doc.data())));
Try passing an empty array as an argument to useEffect like so:
useEffect(() => {
setLoading(true)
checkReturn()
getUser()
}, [])
I am trying to use the Dropdown element of Semantic UI React. It is meant to work with a REST API that allows to get a list of movies. React is configured to fetch data from the appropriate REST API application (this already works for other elements of the frontend).
I would like to get the list of movie names as options. Please have a look at the following JS snippet.
import React, { useState, useEffect } from "react";
import { Dropdown } from "semantic-ui-react";
export const MovieDropdown = () => {
const [movie, setMovie] = useState("");
const [movieOptions, setMovieOptions] = useState([]);
useEffect(() => {
fetch("/movies")
.then((response) => response.json())
.then((data) =>
setMovieOptions(
data.map((x) => {
return { key: x.name, text: x.name, value: x.name };
})
)
);
}, []);
return (
<Dropdown
placeholder="Select Movie"
search
selection
options={movieOptions}
onChange={(e) => setMovie(e.target.value)}
/>
);
};
export default MovieDropdown;
I could not figure it out from https://react.semantic-ui.com/modules/dropdown/#usage-remote.
Your code looks good. Change a small thing and it will work:
onChange={e => setMovie(e.target.value)} // you cannot use event in setState. furthermore checkout the second param of the onChange-Event
to
onChange={(e, {value}) => setMovie(value)}
checkout fixing-react-warning-synthetic-events-in-setstate
here's the full working code
import React, { useState, useEffect } from "react";
import { Dropdown } from "semantic-ui-react";
export const MovieDropdown = () => {
const [movie, setMovie] = useState("");
const [movieOptions, setMovieOptions] = useState([]);
useEffect(() => {
fetch("/movies")
.then((response) => response.json())
.then((data) =>
setMovieOptions(
data.map((x) => {
return { key: x.name, text: x.name, value: x.name };
})
)
);
}, []);
return (
<Dropdown
placeholder="Select Movie"
search
selection
options={movieOptions}
onChange={(e, {value}) => setMovie(value)}
/>
);
};
export default MovieDropdown;