Axios PUT Request in React, Redux Not Working - javascript

So I want to make a PUT request to the server, but it doesn't want to work. I know that when making a PUT request you need an identifier(e.g id) for the resource and the payload to update with. So that is my problem.
In my form I have these props:
<div>
<DoorSettingsForm
onSubmit={this.submit.bind(this)}
item={this.props.location.state.item}
id={this.props.location.state.item._id}
/>
</div>
item - All the input fields, radiobuttons etc.
id - The identifier
onSubmit - the function that handles the submitting of all of the new data, here it is:
submit(values, id) {
this.props.updateSettings(values, id)
}
And inside of my really simple action I have this:
export function updateSettings(id, item) {
return dispatch => {
console.log('ID: ', id)
return axios
.put(`${settings.hostname}/locks/${id}`, item)
.then(res => console.log(res))
.catch(err => console.log(err))
}
}
One thing that I really don't understand is when I change the places of id and item on the first line the output of my console.log changes. When having id as the first parameter I get everything I've typed in my inputs (the changes) and when having item as the first parameter I'm getting this:
ID: function (action) {
if (action.payload) {
if (!(0, _isPromise2.default)(action.payload) && !(0, _isPromise2.default)(action.payload.promise)) {
return next(action);
}
Any help with my problem is really appriciated! Thanks for reading.

I forgot to call handleSubmit with my id:
form onSubmit={() => handleSubmit(id, item)}

Related

Firestore updateDoc by id

I want update informations getting doc by id but I receive erros my code.
Idk how solve this sorry about my english. I just want to update the information I think is a basic error, but I can't solve it sorry
I receive Expected type 'Ta', but it was: a custom Aa object
const updateFields = (e) => {
e.preventDefault()
updateDoc(TopStoryAnswersCollectionRef, {
response_B6: responseB6,
response_B9: responseB9,
response_B12: responseB12,
response_B15: responseB15,
response_B18: responseB18,
response_B21: responseB21,
response_B24: responseB24,
response_B27: responseB27,
response_B28: responseB28,
response_B29: responseB29,
response_B32: responseB32,
response_B33: responseB33,
response_B34: responseB34,
response_B35: responseB35,
response_B38: responseB38,
user_uid: currentUser.uid,
}).then(() => {
alert('Updated')
})
setFormSubmitted(true)
}
Your variable TopStoryAnswersCollectionRef should be a reference to a document when using updateDoc not a reference to a collection. See sample code below:
const updateFields = (e) => {
e.preventDefault()
const TopStoryAnswersCollectionRef = doc(db, "collection-name", "document-id");
updateDoc(TopStoryAnswersCollectionRef, {
response_B6: responseB6,
response_B9: responseB9,
response_B12: responseB12,
response_B15: responseB15,
response_B18: responseB18,
response_B21: responseB21,
response_B24: responseB24,
response_B27: responseB27,
response_B28: responseB28,
response_B29: responseB29,
response_B32: responseB32,
response_B33: responseB33,
response_B34: responseB34,
response_B35: responseB35,
response_B38: responseB38,
user_uid: currentUser.uid,
}).then(() => {
alert('Updated')
})
setFormSubmitted(true)
You could also incorporate a query using where() if you still don't have the document reference to update to.
For more information, you may checkout this documentation.

How to use the updated useState value?

I use DataGrid Material UI.
I want to delete the selected row by clicking on the button.
To do this, I get the ID value in the onRowSelected attribute, write it to the useState hook.
However, when I click on any row, the row I selected earlier is deleted, not the one I selected now.
I know that useState is asynchronous, but what should I do in this case?
I need to send the updated value in the delete request to the server, not the previous one.
const [selectionModel, setSelectionModel] = useState([])
const handleDeleteUser = (e) => {
const config = {
headers: {
Authorization: 'Token ' + localStorage.getItem('token')
}
}
e.preventDefault()
axios
.delete(baseUrl + '/api/v1/users/' + `${selectionModel}/` , config)
.then((res) => {
swal({
title: "Are you sure?",
buttons: [true, "Do it!"],
})
updateData()
})
<DataGrid
rows={datas}
columns={columns}
pageSize={10}
onRowSelected={(row) => {
setSelectionModel(row.data.id)
}} />
picture
From what you've shown here I can't tell you exactly what the issue is, but I would suggest setting the selected id like you currently are here in the onRowSelected event, and then (if you're wanting to delete every time you click a row), use a useEffect hook with a dependency array to call your delete logic everytime that id changes. It would look something like this:
useEffect(() => {
deleteSelection(selectionModal)
}, [selectionModal]);
const deleteSelection = (id) => {
// your delete logic here
}
If you put together a working codepen I can help you more.

How to perform subquery when rendering json data with React?

Edit: Moved the getMetadata() call out of render, as suggested by #Robin Zigmond. Still having trouble getting the proper value from getMetadata() returned, but that's different from my original question. Updating code just for reference.
Quick background: I have a fair amount of experience with shell scripting and stuff like Perl and PHP, but javascript and especially the libraries on top of it like React feel very foreign to me. Forcing myself to develop this with React to teach myself something new, so if you see any bad practices, feel free to suggest improvements!
That said, I'm trying to write a simple app that:
Prompts for search parameter
Runs query against 3rd party service that returns json results
For each returned element, run additional query to get more details
Display tabular results
I have 1, 2, and 4 generally worked out, but struggling with 3. Here's what I have so far, with less important code snipped out:
class VGSC_Search extends React.Component {
constructor() {
super();
this.state = {
submitted: false,
platform: '',
games: [],
metadata: [],
files: [],
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({platform: event.target.value});
}
handleSubmit(event) {
this.setState({submitted: true});
<SNIP - vars>
fetch(encodeURI(searchurl + query + fields + sort + rows))
.then(result => result.json())
.then(data => this.setState({
games: data.response.docs.map(game => ({
identifier: game.identifier,
title: game.title,
creator: game.creator,
year: game.year,
uploader: this.getMetadata(game.identifier),
}))
}));
event.preventDefault();
}
getMetadata(id) {
<SNIP - vars>
fetch(encodeURI(metadataurl + id + metadatainfo))
.then(result => result.json())
.then(data => this.setState({metadata: data.response}));
}
renderResults() {
const {games} = this.state;
const {metadata} = this.state;
return (
<SNIP - table header>
<tbody>{games.map(game =>
<tr key={game.identifier}>
<td><a href={'https://archive.org/details/' + game.identifier}>{game.title}</a></td>
<td>{game.creator}</td>
<td>{game.year}</td>
<td>{game.uploader}</td>
</tr>
)}</tbody>
</table>
);
}
render(){
return (
<div>
<SNIP - form>
<br/>
{this.state.submitted && this.renderResults()}
</div>
);
}
}
My problem is with that Uploader field, which should run getMetadata() on the given identifier and return the name of the uploader. I'm having trouble figuring out how to reference the result, but my biggest problem is actually that my browser keeps running getMetadata() on all displayed items in an endless loop. Eg, from the Developer Tools log:
XHR GET https://archive.org/metadata/4WheelThunderEuropePromoDiscLabel/metadata/uploader [HTTP/1.1 200 OK 105ms]
XHR GET https://archive.org/metadata/AirJapanCompleteArtScans/metadata/uploader [HTTP/1.1 200 OK 279ms]
XHR GET https://archive.org/metadata/AeroWings-CompleteScans/metadata/uploader [HTTP/1.1 200 OK 287ms]
XHR GET https://archive.org/metadata/BioCodeVeronicaLEDCT1210MNTSCJ/metadata/uploader [HTTP/1.1 200 OK 279ms]
XHR GET https://archive.org/metadata/Biohazard2ValuePlusDreamcastT1214MNTSCJ/metadata/uploader [HTTP/1.1 200 OK 282ms]
XHR GET https://archive.org/metadata/4WheelThunderEuropePromoDiscLabel/metadata/uploader [HTTP/1.1 200 OK 120ms]
XHR GET https://archive.org/metadata/AirJapanCompleteArtScans/metadata/uploader [HTTP/1.1 200 OK 120ms]
<SNIP>
The first search returns 5 results, and getMetadata() is run correctly on those five results, but note that it starts repeating. It'll do that endlessly until I reload the page.
I'm guessing that has something to do with running getMetadata() inside a function that's being rendered, but I'm not sure why, and having trouble thinking of a good alternate way to do that.
Can anyone explain why I'm seeing this behavior, and (hopefully) offer a suggestion on how to properly implement this?
Thanks!
The infinite loop happens because you're running getMetadata inside render (or rather inside a function that's called from render) - and that results in changing state, which causes a rerender, and so on in an endless loop.
It's bad practice in any situation to call any function which cause any "side effects" from within render - render should simply determine the output given the component's props and state. Typically data-fetching like you're doing is done inside componentDidMount and/or componentDidUpdate. However in this case, where you appear to need to fetch additional data based on the first response in handleSubmit, it seems that you need to call getMetadata from within the final .then callback of that function.
After your latest edit, I can see the problem with the approach you tried here. this.getMetadata doesn't actually return anything. To fix it, you can return the Promise returned by fetch:
getMetadata(id) {
<SNIP - vars>
return fetch(encodeURI(metadataurl + id + metadatainfo))
.then(result => result.json())
.then(data => this.setState({metadata: data.response}));
}
and then use asyc/await inside handleSubmit, with Promise.all to manage the array:
fetch(encodeURI(searchurl + query + fields + sort + rows))
.then(result => result.json())
.then(async data => {
const games = await Promise.all(data.response.docs.map(async game => ({
identifier: game.identifier,
title: game.title,
creator: game.creator,
year: game.year,
uploader: await this.getMetadata(game.identifier),
})));
this.setState({ games });
});

How to send ID with axios.delete() request

I'm making Todo List project (Pure js) and I'm trying to bind backend (node.js/express.js) with frontend. I'm stuck on the axios.delete(). All i want it to do is:When button "delete" is clicked, delete that item from the page and from the database, but I don't know how to pass the id of that item.
I am new to JavaScript.
const deleteData = () => {
axios.delete('http://localhost:3000/delete/:id', {
})
}
const deleteData = (id) => {
axios.delete('http://localhost:3000/delete/${id}', {
})
}
Did you tried this?
look for Template strings:
https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Template_literals

Use sequelize query results inside a jquery event handler

There is an electron framework that gives you a stripped down browser to build your user interface for the desktop application. In my case, I am using jQuery for DOM navigation, Sequelize to talk to my sqlite database and a couple other libraries.
Let's say I have a text field where the user can type a movie name. My database stores a couple hundred movie names. So I would like to offer the user autocomplete suggestions.
Typically, I would use something like this to register a jQuery handler (this will echo field input back to console):
$('#movie-search-field').on('input', (event) => {
console.log(event.target.val())
})
With sequelize, you would typically have a model (say, Movie) and query it like so: Movie.findAll(). Here comes the problem:
If I register my handler like so:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
then it never gets triggered. I have verified that the .then clause is entered by printing movies to console from within it.
On the other hand, if I try to query the database from inside the handler:
$('#movie-search-field').on('input', (event) => {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
})
})
then the handler exits before the promise is resolved and no suggestions are shown.
How could I use the database query results in my event handler?
You could just make a simple callback
$('#movie-search-field').on('input', (event) => {
getResults(function(movies) {
/* Display your movies */
})
})
function getResults(callback) {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
callback(movies)
})
}
So when a user types in the input box it will request the suggestions and then when it returns them it will call the function (callback) and then you can display them
Turns out I made some unrelated mistakes in my event handler code and so the approach I described above works just fine:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
Also, if you are doing several database queries and would like your handler to have access to all of those, you can do:
let movies = Movie.findAll()
let tickets = Ticket.findAll()
Promise.all([movies, tickets]).then(values => {
let [movies, tickets] = values
/* register your handlers here and pass the data to them */
$("#some-selector").on('input', {movies: movies, tickets: tickets}, (event) => {
let movies = event.data.movies
let tickets = event.data.tickets
/* some event handling code that uses both movies and tickets */
})
})

Categories

Resources