How do I use mongoDb to update value on my database - reactjs

I am building a CRUD app using monogoDb and Reactjs, I need to pass my updated value to replace the old one. I am able to get the ID but I can't seem to pass the value correctly.
jsx for the update input.
...<input
type="text"
placeholder="New food name"
onChange={(event) => {
setNewFoodName(event.target.value)
}}/>
<button onClick={()=>updateInput(item._id)}>Update</button>
my update function
function updateInput(id) {
axios.patch(`http://localhost:3001/update/${id}`, {
di: id,
newFoodName: foodName
}).then(r => {
console.log(r)
})
console.log(newFoodName)
}
my backend using mongodb.
app.patch('/update/:id', (req,res) =>{
const updatedFood = req.body
//console.log(updates.newFoodName)
if(ObjectId.isValid(req.params.id)){
db.collection('foods')
.updateOne({_id: ObjectId(req.params.id)}, {$set: updatedFood})
.then(result =>{
res.status(200).json(result)
})
.catch(err =>{
res.status(500).json({error: "Unable to update item"})
})
}else{
res.status(500).json({err: "Cannot update request"})
}
})

Ok, I was able to fix it from the front-end.
function updateInput(id) {
axios.patch(`http://localhost:3001/update/${id}`, {
id: id,
// newFoodName: newFoodName,
foodName: newFoodName // PASS IN THE foodName to the newFoodName
}).then(r => {
console.log(r)
})
console.log(newFoodName)
}

Related

how to get data from another api and post it with another api in react js

Hi i am working on reactjs with axios. currently i am working on post api and i am working on hybrid form like need some data from get api and some data send by input value. currently i am able to do only one thing. like get value in input field or post value from same input field.but i want to to same thing with one input field. like update field first get data and update it. but in update we use one api and here i m using two api
Post api
handleSubmit = event => {
event.preventDefault();
event.target.reset()
console.log(this.props.rowId);
let rId = this.props.rowId;
const posts = rId;
console.log(posts);
const brokerId = localStorage.getItem("brokerId");
// Based on several assumptions: single obj returned, posts is never empty
axios.post(`http://http:testapi/100/${brokerId}`, {
ipoId: this.props.rowId,
// question: this.state.question,
// answer: this.state.answer,
UCC: this.state.UCC,
NAME: this.state.NAME,
ZONE: this.state.ZONE,
UPDATED_BY: this.state.UPDATED_BY,
// faqList: [
// {
// }
// ]
}).then(res => {
this.getData();
this.setState({
question: ''
})
this.setState({
answer: ''
})
})
.catch(err => {
this.setState({
errorMessage: err.message
});
})
}
handleNAMEChange = event => { this.setState({ NAME: event.target.value }) }
handleUCCChange = event => { this.setState({ UCC: event.target.value }) }
Get Api
getData() {
let rId = this.props.rowId;
axios.get(`http:testapi/100/${rId}`)
.then(res => {
const faq = res.data.body.data.client_detail;
this.setState({
faq
});
})
};
able to get the data from get api in this field
<TextField
type="text"
label="UCC"
value={faqList.clienT_CODE}
name="UCC"
onChange={this.handleUCCChange}
/>
able to post the data from post api in this field
<TextField
type="text"
label="NAME"
value={this.state.NAME}
name="UCC"
onChange={this.handleNAMEChange}
/>

How to customer data in value antd and Put axios

How to customer data in value antd and Put axios
https://ant.design/components/form/
The input does not let me change the data that will be updated by axios
I must still be able to fix it.
I want to show Antd form data. I read the review and use initialValues But I still can't.
componentDidMount () {
let id = this.props.match.params.id;
httpClient
.get(`http://localhost:8085/api/v1/customer/customer/${id}`)
.then((e) => this.setState({
cus_fname: e.data.cus_fname,
cus_lname: e.data.cus_lname,
cus_email: e.data.cus_email,
cus_tel: e.data.cus_tel,
cus_car_number: e.data.cus_car_number,
cus_band: e.data.cus_band,
cus_address: e.data.cus_address,
}));
}
onFinish = async(values) => {
// console.log("ค่า values ที่มาจาก form: ", values);
const formData = new FormData();
formData.append("cus_fname", values.cus_fname);
formData.append("cus_lname", values.cus_lname);
formData.append("cus_email", values.cus_email);
formData.append("cus_tel", values.cus_tel);
formData.append("cus_car_number", values.cus_car_number);
formData.append("cus_band", values.cus_band);
formData.append("cus_address", values.cus_address);
await httpClient
.put(`http://localhost:8085/api/v1/customer/customer/`, formData )
.then((res) => {
// console.log(res.data);
// console.log( "PushData to server success : ", res);
}).catch((error) => {
console.log("Error :", error);
});
await this.props.history.goBack();
};
handleChange = event => {
event.persist();
this.setState({
[event.target.fname]: event.target.value
});
};
render() {
const { fname, lname, email, phone, band, cus_address, car_number} = this.state;
return (
<Form {...layout} name="nest-messages" onFinish{this.updateCustomer} >
<FormItem
label="ชื่อ"
name="fname"
defaultValue={fname}
rules={[{ required: true, message: "โปรดระบุชื่อ ", }]}
onChange={this.handleChange}
>
<Input />
</FormItem>
)
initialValues will show only the state value on the first render, it will not change the value of the form on componentDidMount even you did setState because that will be a second render.. to achieve it you need a reference to the form and use the api of the instance.
//create instance
formRef = React.createRef();
componentDidMount () {
let id = this.props.match.params.id;
httpClient
.get(`http://localhost:8085/api/v1/customer/customer/${id}`)
.then((e) => {
this.formRef.current.setFieldsValue({
cus_fname: e.data.cus_fname,
cus_lname: e.data.cus_lname,
cus_email: e.data.cus_email,
cus_tel: e.data.cus_tel,
cus_car_number: e.data.cus_car_number,
cus_band: e.data.cus_band,
cus_address: e.data.cus_address,
});
//you can still do a setState
/*this.setState({
cus_fname: e.data.cus_fname,
cus_lname: e.data.cus_lname,
cus_email: e.data.cus_email,
cus_tel: e.data.cus_tel,
cus_car_number: e.data.cus_car_number,
cus_band: e.data.cus_band,
cus_address: e.data.cus_address,
});*/
})
}
and in the Form component:
<Form ref={this.formRef} {...layout} name="nest-messages" onFinish={this.updateCustomer} >
...
</Form>
take note that there is no onChange callback on <Form.Item> component on antd documentation. If you want to change the state on every change, use onValuesChange props of the Form.
<Form onValuesChange={(changedValues, allValues) => {
/* perform setState */
}}>
</Form>
You may also want to look on this link for more info.

useState referring to stale value

I have a keeper app where I am adding notes and storing them in database. When I make a post request to the server, I am trying to fetch the _id from database, which will eventually help me to later delete the note ( if needed).
Here is my jsx file
function CreateMessage(props) {
const [currentGuest, setCurrentGuest] = useState({
guestName: '',
guestMessage: '',
id:''
});
function handleMessages(event) {
const {name, value} = event.target;
setCurrentGuest(prevGuest => {
return {
...prevGuest,
[name] : value
};
});
}
function submitMessage(event) {
//props.onAdd(currentGuest);
const params = {
guestName: currentGuest.guestName,
guestMessage: currentGuest.guestMessage,
}
axios
.post("http://localhost:8000/notes", params)
.then(res => {
console.log("The response is"+res.data._id);
console.log(res.status);
setCurrentGuest(prevGuest => {
console.log(res.data._id)
return {
...prevGuest,
id: res.data._id
};
});
console.log(currentGuest);
})
event.preventDefault();
}
return (
<div>
<form>
<input
name="guestName"
placeholder="Guest Name"
value={currentGuest.guestName}
onChange={handleMessages}
/>
<textarea
name="guestMessage"
placeholder="Write a Message"
rows="3"
value={currentGuest.guestMessage}
onChange={handleMessages}
/>
<button onClick={submitMessage}>Add</button>
</form>
</div>
);
}
The id is properly being fetched and displayed in ```console.log("The response is"+res.data._id"). But on first submit, the is always empty and stale id gets attached to the currentGuest object on next submit
function submitMessage(event) {
//props.onAdd(currentGuest);
const params = {
guestName: currentGuest.guestName,
guestMessage: currentGuest.guestMessage,
}
axios
.post("http://localhost:8000/notes", params)
.then(res => {
console.log("The response is"+res.data._id);
console.log(res.status);
setCurrentGuest(prevGuest => {
console.log(res.data._id)
return {
...prevGuest,
id: res.data._id
};
});
console.log(currentGuest);
})
event.preventDefault();
}
In the above snippet, after getting the response you're correctly changing the state but the problem is with where you're checking the changed state(console.log(currentGuest)). You're basically logging before the state is changed.
You can use useEffect hook and log the state inside it. This runs every time the currentGuest Changes.
useEffect(() => {
console.log(currentGuest)
}, [currentGuest])
Update
You can use the modified currentGuest inside the useEffect hook:
useEffect(() => {
console.log(currentGuest)
if(currentGuest.id) {
props.onAdd(currentGuest);
// You can also reset the state here as follows
setCurrentGuest({
guestName: '',
guestMessage: '',
id:''
});
}
}, [currentGuest]) // You might need to add the necessary dependencies to this array.

Optional field inside Options React Select

Hey guys im trying to create a autosuggestion in cooperation with redux-form. Im using the Creatable approach. I loading my options via an external API. The problem is, i need a extra field in every Option Object. {value: "test#gmx.de", label: "test#gmx.de", dn:"CN...." }. Is there a possibility to do so?
I typically add my own properties inside the callback for the API request, just before setting the options in the state. For example...
axios.get('/some/api/request')
.then(response => {
const options = response.data.map(item => {
// Add whatever custom properties you want here
return ({value: "test#gmx.de", label: "test#gmx.de", dn:"CN...." })
})
// set your options in the state to the new options constant from above
dispatch(change('formName', 'options', options))
Hope this helps!
//Handle change with either selectedOption
handleChange(selectedOption){
this.setState({ selectedOption })
if(this.props.onOptionSelect){
this.props.onOptionSelect(selectedOption.data)
}
}
loadOptions(input, callback) {
this.props.loadOptions(input).then(options => {
callback(null, {options: options})
})
}
render() {
const {selectedOption} = this.state
const selectClass = this.props.meta.touched && this.props.meta.error ? "has-error form-group" : "form-group"
return (
<div className={selectClass}>
<AsyncCreatable
value={selectedOption}
onChange={this.handleChange}
loadOptions={this.loadOptions}
isLoading={false}
placeholder={this.props.label}
promptTextCreator={(label) => this.props.promtLabel(label)}
onBlur={() => this.props.input.onBlur(selectedOption.value || "")}
/>
</div>
)
}
//Function to convert incomming users in usable options (React Select)
export const convertADUsersToOptions = users => {
return users.map(user => {
return {
value: normalizeDN(user.dn),
label: user.mail
}
})
}

React - Json Schema Form dropdowns won't load initally unless I use SetTimeout function

This has been driving me and my team crazy. Here is the relevant code.
In the component's CDM we have:
componentDidMount() {
this.getContextID();
this.getConsumerID();
this.getEnvType();
//setTimeout(() => this.setState({ populatedMultiSchema: this.multiSchema }), 200);
//setTimeout(() => this.setState({ populatedMultiUISchema: this.multiUISchema }), 200);
this.setState({ populatedMultiSchema: this.multiSchema });
this.setState({ populatedMultiUISchema: this.multiUISchema });
}
so any one of the 3 methods listed will fetch the data for the dropdown. Here is an example of one (they are all basically the same).
getContextID() {
contextIDOptions = [];
console.log("CONVERT_TARGET::", this.props.fetchTarget)
return (
fetch(this.props.fetchTarget + "Configuration/ContextIDs", {
method: 'GET',
//mode: 'cors',
credentials: 'include',
}).then(response => {
if (response.status >= 400) {
this.setState({
value: 'no response - status > 400'
});
throw new Error('no response - throw');
}
return response.json()
}).then(function (json) {
for (var contextID = 0; contextID < json.List.length; contextID++) {
contextIDOptions.push(json.List[contextID]);
}
this.setState({ contextIDArray: contextIDOptions });
console.log("got contextIDs");
}.bind(this)).catch(() => {
this.setState({
value: 'no response - cb catch'
})
})
)
}
So we set the state there to 'contextIDArray'.
Then the JSON Schema form through it's multiUISchema Object has references to these widgets that help set the values for the form.
ContextIDWidget = (props) => {
return (
<div>
<input type="text" placeholder="Select one..." className="form-control" list="contextIDSelect" onChange={(event) => props.onChange(event.target.value)} />
<datalist id="contextIDSelect">
{this.state.contextIDArray.map((value, index) => { return <option key={index} value={value}>{value}</option> })}
</datalist>
</div>
)
}
This is the multiUISchema object (the part that matters for this discussion)
multiUISchema = {
file: {
'ui:widget': this.MultiFileWidget,
classNames: "uiSchema"
},
contextID: {
'ui:widget': this.ContextIDWidget,
classNames: "uiSchema"
},
}
And finally here it is in the return in the component.
return (
<div className="container" >
<Form
schema={this.state.populatedMultiSchema}
uiSchema={this.state.populatedMultiUISchema}
formData={this.state.formData}
onChange={({ formData }) => { this.setState({ formData }); this.setState({ totalFileSize: this.getMultiFileSize() }); this.checkConversionSupport() }}
onSubmit={this.handleSubmit}
>
So long story short, if Im using state object in the form, and Im doing setState on the objects Im using. Why do I always get a blank dropdown when I first load the component. Shouldn't the DOM (the dropdown in this case) get repainted with the updated data from the fetches when the state object is changed? I have console logs that show the fetched data in my inspection window so I know the data has been fetched. This is tab component. If I leave the tab or navigate to another page in my SPA and then go back to this page, then the dropdowns are all fully loaded. But I can never get it just load initially unless I set these timeouts in CDM instead of just setting state.
setTimeout(() => this.setState({ populatedMultiSchema: this.multiSchema }), 200);
setTimeout(() => this.setState({ populatedMultiUISchema: this.multiUISchema }), 200);
I know the post is long but felt I needed to include all the parts to get help with this. I can assure you we have been trying to resolve the issue for over a week. We welcome any comments. Thanks!
I am not fully familiar to your codebase. But it looks like something related about asynchronous requests. Here:
this.setState({ populatedMultiSchema: this.multiSchema });
this.setState({ populatedMultiUISchema: this.multiUISchema });
These two lines will be executed BEFORE these ones:
this.getContextID();
this.getConsumerID();
this.getEnvType();
But you expect them to get executed in reverse order. No. Your getContextID method making a request to a server. Javascript is asynchronous. But, by using await expression in an asynchronous function, you can pause the execution and wait for the Promise.
So, just update your componentDidMount method as below:
async componentDidMount() {
await this.getContextID();
await this.getConsumerID();
await this.getEnvType();
this.setState({ populatedMultiSchema: this.multiSchema });
this.setState({ populatedMultiUISchema: this.multiUISchema });
}
Here i created a Codepen on usage of async/await. There are some details in comments. You can play with it as you want.
Even if your problem is not caused mainly by this, this approach is better. You should either use async/await or Promise to work with network requests.

Resources