RestaurantList.js
import React, { Component } from "react";
import { Table } from 'react-bootstrap';
import { Link } from 'react-router-dom'
export default class RestaurantList extends Component {
constructor() {
super();
this.state = {
list: null,
};
}
componentDidMount() {
fetch("http://localhost:3000/restaurant").then((response) => {
response.json().then((result) => {
this.setState({ list: result });
});
});
}
render() {
return (
<div>
<h1>List</h1>
{
this.state.list ?
<div>
<Table striped bordered hover>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Rating</th>
<th>City</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
{
this.state.list.map((item, i) =>
<tr>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.rating}</td>
<td>{item.address}</td>
<td><Link to={"/update/" item.id} style={{ color: 'blue', textDecoration: 'inherit' }}>Edit</Link></td>
</tr>)
}
</tbody>
</Table>
</div>
:
<p>Please Wait...</p>
}
</div>
);
}
}
RestaurantUpdate.js
In Class Component Method (It is correct)
import React, { Component } from 'react';
import NavBarManu from './NavBarManu'
class RestaurantUpdate extends Component {
constructor()
{
super();
this.state = {
name: null,
email: null,
address: null,
rating: null,
id:null,
}
}
componentDidMount()
{
fetch('http://localhost:3000/restaurant/' this.props.match.params.id).then((response) => {
response.json().then((result) => {
console.warn(result)
this.setState({
name:result.name,
email:result.email,
id:result.id,
rating:result.rating,
address:result.address
})
})
})
}
update()
{
fetch('http://localhost:3000/restaurant/' this.state.id, {
method: "PUT",
headers:{
'Content-Type':'application/json'
},
body: JSON.stringify(this.state)
}).then((result)=>{
result.json().then((resp)=>{
alert("Restaurant has heen Update")
})
})
}
render() {
return (
<div>
<NavBarManu />
<h1>Restaurant Update</h1>
<div>
<input onChange={(event) => { this.setState({ name: event.target.value }) }}
placeholder="Restaurant Name" value={this.state.name} /> <br /><br />
<input onChange={(event) => { this.setState({ email: event.target.value }) }}
placeholder="Restaurant Email" value={this.state.email} /> <br /><br />
<input onChange={(event) => { this.setState({ rating: event.target.value }) }}
placeholder="Restaurant Rating" value={this.state.rating}/> <br /><br />
<input onChange={(event) => { this.setState({ address: event.target.value }) }}
placeholder="Restaurant Address" value={this.state.address}/> <br /><br />
<button onClick={() => { this.update() }}>Update Restaurant</button>
</div>
</div>
);
}
}
export default RestaurantUpdate;
In Functional Component(Facing some errors)
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
const RestaurantUpdate = () => {
const [name, setName] = useState(null);
const [email, setEmail] = useState(null);
const [address, setAddress] = useState(null);
const [rating, setRating] = useState(null);
const [id, setId] = useState(null);
//Want to use it like CompoundDidMount
useEffect(() => {
fetch('http://localhost:3000/restaurant' / id).then((response) => {
response.json().then((result) => {
console.warn(result)
setName(result.name);
setEmail(result.email);
setId(result.id);
setAddress(result.address);
setRating(result.rating);
})
})
}, []);
//Want to display all the states in the console with their respective values. But i am unable to do it.
useEffect(() => {
console.warn(name);
}, [id]);
return (
<div>
<h1>Update</h1>
<div>
<input onChange={(event) => { this.setState({ name: event.target.value }) }}
placeholder="Restaurant Name" /> <br /><br />
<input onChange={(event) => { this.setState({ email: event.target.value }) }}
placeholder="Restaurant Email" /> <br /><br />
<input onChange={(event) => { this.setState({ rating: event.target.value }) }}
placeholder="Restaurant Rating" /> <br /><br />
<input onChange={(event) => { this.setState({ address: event.target.value }) }}
placeholder="Restaurant Address" /> <br /><br />
<button onClick={() => { this.update() }}>Update Restaurant</button>
</div>
</div>
);
};
export default RestaurantUpdate;
I was expecting display of all the state in the console with the their respective data. But it is showing null values. I am facing some errors in implementing componentDidMount() in function component using hooks and in setState(). Basically I just want to use given Class Component RestaurantUpdate.js in functional component way. Definitely there are some syntax errors and i am facing some difficulties in implementing them. So please point out the error and provide me the right solution.
Blockquote
CodePudding user response:
Add a conditional render and see if it works.
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
const RestaurantUpdate = () => {
const [name, setName] = useState(null);
const [email, setEmail] = useState(null);
const [address, setAddress] = useState(null);
const [rating, setRating] = useState(null);
const [id, setId] = useState(null);
const [result, setResult] = useState(null);
//Want to use it like CompoundDidMount
useEffect(() => {
fetch('http://localhost:3000/restaurant' / id).then((response) => {
response.json().then((result) => {
console.warn(result)
setResult(result);
setName(result.name);
setEmail(result.email);
setId(result.id);
setAddress(result.address);
setRating(result.rating);
})
})
}, []);
//Want to display all the states in the console with their respective values. But i am unable to do it.
useEffect(() => {
console.warn(name);
}, [id]);
return (
<>
{
result ? (
<div>
<h1>Update</h1>
<div>
<input onChange={(event) => { setName(event.target.value) }} value={name}
placeholder="Restaurant Name" /> <br /><br />
<input onChange={(event) => { setEmail(event.target.value) }} value={email}
placeholder="Restaurant Email" /> <br /><br />
<input onChange={(event) => { setRating(event.target.value) }} value={rating}
placeholder="Restaurant Rating" /> <br /><br />
<input onChange={(event) => { setAddress(event.target.value) }} value={address}
placeholder="Restaurant Address" /> <br /><br />
<button onClick={() => { update() }}>Update Restaurant</button>
</div>
</div>
) : (<div>loading</div>)
}
</>
);
};
export default RestaurantUpdate;
CodePudding user response:
There are a few things to address here that probably will help you to achieve the desired result.
First is the id
, probably it should come from the a call to useParams
right? if so, no need to declare it as a state.
const { id } = useParams();
Then, in the useEffect
even though you want to simulate compoundDidMount
the recommended solution is to include in the deps array all the values used internally in the useEffect
. this link hooks docs is super helpful.
Next, you probably is having some warnings in the console
complaining about "value" prop on "input" should not be null
and A component is changing an uncontrolled input to be controlled
, this can be avoided just by setting an initial state for the inputs different of null
or undefined
, and this could be:
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [address, setAddress] = useState("");
const [rating, setRating] = useState(0);
or also by using the technique displayed in the previous answers will help you to remove from these warnings.
Also in your example the value
field was missing in the inputs
<input
onChange={(event) => setName(event.target.value)}
placeholder="Restaurant Name"
value={name} />
And I guess with these tweaks you should be fine. I've put together a sandbox that might help you to unfold everything. example