How to re-render component with react hooks - javascript

I'm completely new to React and I'm trying to use the React Hooks. I have a functional based component and I'm using the useState and useEffect to get users from my database and display them in a table.
Now, I also have a delete button for each row of my table. When I click on the delete button, I execute a delete function which deletes the data from my database. This works well. However, the table is not updated unless I refresh the whole page completely.
How can I update (re-render) my users table once the delete is done.
Below is a snippet of my code:
const [users, listUsers] = React.useState([]);
React.useEffect(() => {
axios
.get(GET_URL)
.then(res => {
console.log(res.data);
listUsers(res.data);
})
.catch(err => console.log(err));
}, []);
const deleteUser = async id => {
await fetch(DELETE_URL, {
//JSon message
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: id
})
})
.then(response => response.text())
.then(responseJson => {
console.log(JSON.stringify(responseJson));
})
.catch(error => {
console.error(error);
});
alert('User Deleted.');
};

You are not updating your list of users state once deletion You have update your list of users state. You can do this by:
const deleteUser = async id => {
await fetch(DELETE_URL, {
//JSon message
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: id
})
})
.then(response => response.text())
.then(responseJson => {
console.log(JSON.stringify(responseJson));
})
.catch(error => {
console.error(error);
});
const usersUpdated = users.filter(p => p.id !== id); //Filter your list of users and remove the one for the specific id
listUsers(usersUpdated); //This updates your state
alert('User Deleted.');
};
;)

Related

Trying to access specific id in another page by the [id].svelte route in svelte

I am trying to show the details of my airtable content in another page based of id.
This is my file structure:
On my about page(yes I used svelte kit to create my app.) I called the api and I'm looping through it. I can see my test content and its working fine:
onMount(() => {
fetch("https://api.airtable.com/v0/apikey/etc", {
method: "get",
headers: new Headers({ Authorization: "Bearer apikey" }),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
records = data.records;
console.log(records[1].fields.Name);
})
.catch((error) => {
console.log(error);
});
});
And I'm looping through it:
{#each records as record, i}
<a href={`/listOfStuff/${record.id}`}>{record.id}</a>
<p>{record.fields.Name}</p>
{/each}
So in my [id].js I tried to load specific data by doing this.I tried accessing the id parameter:
let id=$page.params.id;
Then tried loading the data:
onMount(() => {
fetch("https://api.airtable.com/v0/apikey/etc"+id, {
method: "get",
headers: new Headers({ Authorization: "Bearer apikey" }),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
records = data.records;
console.log(records[1].fields.Name);
})
.catch((error) => {
console.log(error);
});
});
</script>
onMount(() => {
fetch("https://api.airtable.com/v0/apikey/Names"+id, {
method: "get",
headers: new Headers({ Authorization: "Bearer apikey" }),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
records = data.records;
console.log(records[1].fields.Name);
})
.catch((error) => {
console.log(error);
});
});
</script>
Then tried accessing it:
{#each records as record, i}
<p>{record.id}</p>
<p>{record.fields.Name}</p>
{/each}
But when I try navigating to it from my about page and click on the href I dont see anything loading afterwards. The route takes me to the route of the specific id but the page itself is blank. That's why I am very confused.
Anyone has any ideas?
I had a typo in the link. That was the issue. I'm sorry it took me too long to realize it.

Get response.data from fetch() as variable to use in React-Native

I've seen several posts about this, so I apologize if it's a direct duplicate. The examples I've seen have the RN components built with classes. I'm using functions, and I'm new, so it's all very confusing.
const getFlights = async () => {
const token = await getAsyncData("token");
instance({
method: "get",
url: "/api/flights/",
headers: {
Authorization: `Token ${token}`,
},
})
.then(function (response) {
// console.log(response.data.results); // shows an array of JSON objects
return response.data.results; // I've also tried response.data.results.json()
})```
I just want the response returned as a variable that I can use to populate a FlatList component in RN.
const FlightListScreen = () => {
const [list, setList] = useState([]);
const flights = getFlights(); // currently returns as a promise object
Thank you for your help.
I think you have to store the response object directly to the json method. And then with that response you can store it to the variable
.then(response => { return response.json() })
.then(response => {
this.setState({
list: response
})
you are sending token without a bearer. Concrete your token with bearer like this
headers: {
Authorization: "Bearer " + token,
},
and another thing is your response class are not right this should be like this
.then((response) => response.json())
.then((responseJson) => {
API will Resopne here....
}
this is a complete example to call API with Token
fetch("/api/flights/", {
method: "GET",
headers: {
Authorization: "Bearer " + token,
},
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
setState(responseJson.VAlue);
})
.catch((error) => {
alert(error);
});

How can I refactor my POST fetch function to be more async with Redux?

I am fairly new to using react with redux especially when it comes to making certain functions async. Just curious about the steps someone would take to go about it. Below is my current POST function with some added Redux code.
createCheckList = (title) => {
if (!(title === '')) {
fetch('http://localhost:3001/api/v1/check_lists', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ check_list: {title: title }})})
.then((resp) => resp.json())
.then(data => {
this.props.dispatch(addCheckList(data.id, data.title))
})
.catch(error => console.log(error))
}
}

Wait for parent state to update before calling another function

I'm calling a function that needs to do 2 things:
Call a parent-level function to update my database using a fetch request and then update my parent-level state
Wait for 1st function to update my state, and then route to a view where my updated data is seen (using props)
The problem is I'm not sure how to wait for this 1st function to be complete before moving on to the 2nd. So when I try to change views with this 2nd function, the data shown isn't updated.
The parent-level function that I would like to run and update my state.
updateEntry = (newHeader, newBody, index) => {
fetch("http://localhost:3000/update", {
method: 'PUT',
body: JSON.stringify({
header: newHeader,
body: newBody,
index: index
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => { this.setState({journalDb: data })})
}
The child level function where I call the parent level function using updateEntry()
initiateUpdate = (e) => {
e.preventDefault();
this.props.updateEntry(value1, value2, value3)
this.props.setEditMode();
}
The issue is my parent level state isn't updating in time to show when I change the route using setEditMode()... I'm not sure how to wait for the parent state to update before running this
so what you could do is do something like this
updateEntry = (newHeader, newBody, index) => {
return new Promise((resolve) =>fetch("http://localhost:3000/update", {
method: 'PUT',
body: JSON.stringify({
header: newHeader,
body: newBody,
index: index
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
this.setState({journalDb: data })
resolve()
})
})
and simply add
initiateUpdate = (e) => {
e.preventDefault();
this.props.updateEntry(value1, value2, value3)
.then(() => this.props.setEditMode());
}
this way you're guaranteed that updateEntry was finished when setEditMode is called
Just change your updateEntry function to return the result of the fetch, as this is a promise. For example:
updateEntry = (newHeader, newBody, index) => fetch("http://localhost:3000/update", {
Then when you call the parent function, treat it just like a promise:
this.props.updateEntry(value1, value2, value3).then(() => {
this.props.setEditMode()
})

How to re-render list automatically when form is submitted in React.js

I just figured out how to get and post data to database. The data is displayed in a list when page renders. I want the list to re render when the form input is submitted. As of now I have to refresh the page manually in order to get the new item to show in the list.
I have already tried to create a state change in the handleSubmit function. Nothing seems to happen though.
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost:5000/api/listitems', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify( {
//ID : this.state.id,
Content: this.state.content,
List_Group: this.state.listgroup,
Date_Added: this.state.date
})
})
.then(res => res.json())
.catch(err => console.log(err));
}
Below is the form and list code
<h1>Submit an Item</h1>
<form onSubmit={this.handleSubmit} style={formStyle}>
<label>
Content:
<input type="text" value={this.state.content} onChange=
{this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
<h1>Grocery List</h1>
{this.state.items.map(
(item, i) =>
<p key={i}>{item.List_Group}: {item.Content}</p>
)}
The list should show the new item on submit automatically.
Keeping in mind I have zero practical knowledge of react, it seems to me you simply have to update the this.state.items array.
I assume that your component has some sort of loadItems method, so I would say that your then should look something more like .then(() => this.loadItems())
UPDATED:
//fetch data from server
handleData = () => {
fetch('http://localhost:5000/api/listitems')
.then(response => response.json())
.then(data => this.setState({ items: data }));
}
//call handleData() on page load
componentDidMount() {
this.handleData();
}
//this function fires when form is submited
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost:5000/api/listitems', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify( {
Content: this.state.content,
List_Group: this.state.listgroup,
Date_Added: this.state.date
})
})
.then(res => res.json())
.then(() => this.setState({content: ''}))
//call handleData() when form is submited, which reloads list
.then(() => this.handleData())
.then(console.log(this.state.items))
.catch(err => console.log(err));
}
So the handleData() fetched the data from the server. It is called in componentDidMount() for the initial page load. Then it is called again each time the handleSubmit() function is called by the form. Each time handleData() is called it re-renders the list.
Set the state of your list of items after getting the response.
here i am assuming that you are getting the whole list in response.
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost:5000/api/listitems', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify( {
//ID : this.state.id,
Content: this.state.content,
List_Group: this.state.listgroup,
Date_Added: this.state.date
})
})
.then(res => res.json())
.then(data => this.setState({items : data})
.catch(err => console.log(err));
}
You need to call this.setState. State updates trigger a rerendering.
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost:5000/api/listitems', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify( {
//ID : this.state.id,
Content: this.state.content,
List_Group: this.state.listgroup,
Date_Added: this.state.date
})
})
.then(res => {
// depending on the response you may need to extract the property here
this.setState({
items: res.json(),
});
})
.catch(err => console.log(err));
}
You may do this:
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost:5000/api/listitems', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify( {
//ID : this.state.id,
Content: this.state.content,
List_Group: this.state.listgroup,
Date_Added: this.state.date
})
})
.then(res => res.json())
.then((items) => this.setState({items: items})) // keep in mind that you may have to transform items to appropriate format to display
.catch(err => console.log(err));
}

Categories