React error: warning maximum update depth exceeded - javascript

I have added a screen from where admin can add products to store. Whenever I try to enter this page I get following warning and it keeps on repeating until my browser freezes or crashes:
Maximum update depth exceeded. This can happen when a component calls
setState inside useEffect, but useEffect either doesn't have a
dependency array, or one of the dependencies changes on every render.
Here is the code for my ProductEditScreen.js
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import ErrorMessage from "../../components/ErrorMessage/ErrorMessage";
import Loader from "../../components/Loader/Loader";
import { Link } from "react-router-dom";
import { listProductDetails } from "../../redux/actions/productActions";
import "./ProductEditScreen.scss";
const ProductEditScreen = ({ match, history }) => {
const productID = match.params.id;
const [name, setName] = useState("");
const [price, setPrice] = useState(0);
const [image, setImage] = useState("");
const [brand, setBrand] = useState("");
const [category, setCategory] = useState("");
const [countInStock, setCountInStock] = useState(0);
const [description, setDescription] = useState("");
const dispatch = useDispatch();
const productDetails = useSelector((state) => state.productDetails);
const { loading, error, product } = productDetails;
useEffect(() => {
if (!product.name || product._id !== productID) {
dispatch(listProductDetails(productID));
} else {
setName(product.name);
setPrice(product.price);
setImage(product.Image);
setBrand(product.brand);
setCategory(product.category);
setCountInStock(product.setCountInStock);
setDescription(product.description);
}
}, [dispatch, history, product, productID]);
const submitHandler = (e) => {
e.preventDefault();
};
return (
<>
<div className="userEdit-container">
{/* {loadingUpdate && <Loader />}
{errorUpdate && <ErrorMessage>{errorUpdate}</ErrorMessage>} */}
<div className="userEdit-form">
<h1>EDIT PRODUCT</h1>
{error ? (
<ErrorMessage>{error}</ErrorMessage>
) : (
<form onSubmit={submitHandler}>
<div className="userEdit-form-items">
<input
className="userEdit-input"
type="name"
placeholder="name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input
className="userEdit-input"
type="number"
placeholder="Price"
value={price}
onChange={(e) => setPrice(e.target.value)}
/>
<input
className="userEdit-input"
type="text"
placeholder="Enter image url"
value={image}
onChange={(e) => setImage(e.target.value)}
/>
<input
className="userEdit-input"
type="text"
placeholder="Brand Name"
value={brand}
onChange={(e) => setBrand(e.target.value)}
/>
<input
className="userEdit-input"
type="text"
placeholder="Category"
value={category}
onChange={(e) => setCategory(e.target.value)}
/>
<input
className="userEdit-input"
type="number"
placeholder="Count In Stock"
value={countInStock}
onChange={(e) => setCountInStock(e.target.value)}
/>
<input
className="userEdit-input"
type="text"
placeholder="Description"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
<button type="submit" value="submit">
UPDATE
</button>
<Link to="/admin/productlist">
<button>Go Back</button>
</Link>
</div>
</form>
)}
</div>
</div>
</>
);
};
export default ProductEditScreen;
warning says useEffect either doesn't have a dependency array but I have passed all the dependencies. Also, I don't see any dependency changing every render.

As Chris G suggested above in comments I first ran useEffect with empty [] and then added what console recommended me.
useEffect(() => {
if (!product.name || product._id !== productID) {
dispatch(listProductDetails(productID));
} else {
setName(product.name);
setPrice(product.price);
setImage(product.Image);
setBrand(product.brand);
setCategory(product.category);
setCountInStock(product.setCountInStock);
setDescription(product.description);
}
}, [
dispatch,
productID,
product.Image,
product._id,
product.brand,
product.name,
product.price,
product.category,
product.setCountInStock,
product.description,
]);

Related

Facing some errors while implementing a class component method to functional component method in a restaurant rating management project

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
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;
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

TypeError: Converting circular structure to JSON when sending a post request through axios

Im getting this error when I send a post request to the server when the role for the user is seller for which there are 2 extra properties for the JSON : resName and resAddress. I am also using placeautocomplete (from google) to get the address of the restaurant (the name of it can be anything for the time being).
Register.js:
import logo from './logo.svg';
import './App.css';
import React, { Component, useEffect } from 'react';
import { useState } from 'react';
import axios from 'axios';
import LocationSearchInput from './placeComplete';
function Register() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [role, setRole] = useState("seller");
const [resName, setResName] = useState("");
const [resAddress, setResAddress] = useState(React.createRef());
async function registerUser(e){
e.preventDefault();
if (role === 'seller'){
const restaurantAddress = resAddress.current
console.log(restaurantAddress.state.address, resName)
}
const response = await axios.post('/api/users/register',
{
name,
email,
password,
resName,
resAddress,
role
}
).then(
res => {
console.log(res.data)
}
)
}
function registerRestaurant(){
if (role === 'seller'){
return(
<div>
<h4>Restaurant Name:</h4> <br />
<input type='text'
placeholder='Restaurant Name'
value={resName}
onChange={(e) => setResName(e.target.value)}
/>
<br />
<LocationSearchInput ref={resAddress} />
</div>
);
}
}
return (
<div>
<form onSubmit={registerUser}>
<input type="name" placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<br />
<input type="email" placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<br />
<input type="password" placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<br />
<input type='radio' value='customer'
checked={role === 'customer'}
onChange={(e) => {
setRole(e.target.value)
}}
/>
customer
<br />
<input type='radio' value='seller'
checked={role === 'seller'}
onChange={(e) => {
setRole(e.target.value)
}}
/>
seller
<br />
{registerRestaurant()}
<input type='submit' value='Register' />
</form>
</div>
);
}
export default Register;
placeComplete.js:
import React from 'react';
import PlacesAutocomplete, {
geocodeByAddress,
getLatLng,
} from 'react-places-autocomplete';
class LocationSearchInput extends React.Component {
constructor(props) {
super(props);
this.state = { address: '' };
}
handleChange = address => {
this.setState({ address });
};
handleSelect = address => {
geocodeByAddress(address)
.then(results => getLatLng(results[0]))
.then(latLng => console.log('Success', latLng))
.then(this.setState({address: address}))
.catch(error => console.error('Error', error));
};
render() {
return (
<PlacesAutocomplete
value={this.state.address}
onChange={this.handleChange}
onSelect={this.handleSelect}
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div>
<input
{...getInputProps({
placeholder: 'Search Places ...',
className: 'location-search-input',
})}
/>
<div className="autocomplete-dropdown-container">
{loading && <div>Loading...</div>}
{suggestions.map(suggestion => {
const className = suggestion.active
? 'suggestion-item--active'
: 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div
{...getSuggestionItemProps(suggestion, {
className,
style,
})}
>
<span>{suggestion.description}</span>
</div>
);
})}
</div>
</div>
)}
</PlacesAutocomplete>
);
}
}
export default LocationSearchInput;
I am also getting the following warning when I start typing in resAddress:
react_devtools_backend.js:4026 Warning: Each child in a list should have a unique "key" prop. Check the render method of `PlacesAutocomplete`. See https://reactjs.org/link/warning-keys for more information.
Mind you the server is accepting requests through postman.
This error usually gets thrown if you're not sending proper JSON. Your problem seems to happen here:
const response = await axios.post('/api/users/register',
{
name,
email,
password,
resName,
resAddress,
role
}
).then(
res => {
console.log(res.data)
}
)
Since resAddress is a ref (not proper JSON):
const [resAddress, setResAddress] = useState(React.createRef());
Change to something like this and you should be fine:
{
/* ... */
resAddress: resAddress.current.state.address
/* ... */
}

i am not getting displayed the post

in this i have put request the api its being consoled i want to show it on my screen like crud can anyone help me with it i have used axios.put i think i havnt added the code plaese help me.please help me with this i am a beginner in react.
my api link [restapi]
i am posting my code bekow please go through it:
import axios from "axios";
import react, { useEffect, useState } from "react";
import './App.css'
export default function App() {
const [users, setUsers] = useState([]);
const [searchTerm, setsearchTerm] = useState("");
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const postData =(e)=>{
e.preventDefault();
axios.post("https://reqres.in/api/users?page=1",{
title,
body
} ).then(res=>console.log('posting',res))
}
useEffect(() => {
axios.get("https://reqres.in/api/users?page=1").then((res) => {
setUsers(res.data);
});
}, []);
return (
<div className="App">
<div className="flex">
<input
onChange={(e) => {
setsearchTerm(e.target.value);
} }
type="text"
placeholder="search"
className="form-control"
style={{
width: "80%",
borderRadius: "30px 0 30px",
justifyContent: "center",
marginLeft: "100px",
}} />
<br/>
<br/>
<form>
<label>first_name</label>
<input value={title} onChange={(e)=>setTitle(e.target.value)}/>
<label>email</label>
<input value={body} onChange={(e)=>setBody(e.target.value)}/>
<button onClick={postData}>post</button>
{users?.data?.filter((val) => {
if (searchTerm === "") {
return val;
} else if (val.first_name.toLowerCase().includes(searchTerm.toLowerCase())) {
return val;
}
}).map((datas) => (
<div key={datas.id}>
<p>
<strong>{datas.first_name}</strong>
</p>
<p>{datas.email}</p>
<img key={datas.avatar} src={datas.avatar} />
</div>
))}
</form>
</div>
</div>
);
}
Try the below code. I hope that's how you wanted it to work.
Post request to api - https://reqres.in/api/users?page=1 return data in different form than the api - https://reqres.in/api/users?page=1. So in order to add and show the entered data in the users list, you have to customized the data before adding it to the users useState. Like this:
setUsers([
...users,
{
id: res.data.id,
first_name: res.data.title,
email: res.data.body,
avatar: "https://reqres.in/img/faces/5-image.jpg",
},
]);
Note - I have used a random image while adding the entered data to the users list. As no avatar was being returned from the api.
Full working code:
import axios from "axios";
import react, { useEffect, useState } from "react";
import "./App.css";
export default function App() {
const [users, setUsers] = useState([]);
const [searchTerm, setsearchTerm] = useState("");
const [title, setTitle] = useState("");
const [body, setBody] = useState("");
const postData = (e) => {
e.preventDefault();
axios
.post("https://reqres.in/api/users?page=1", {
title,
body,
})
.then((res) => {
setUsers([
...users,
{
id: res.data.id,
first_name: res.data.title,
email: res.data.body,
avatar: "https://reqres.in/img/faces/5-image.jpg",
},
]);
});
};
useEffect(() => {
axios.get("https://reqres.in/api/users?page=1").then((res) => {
setUsers(res.data.data);
});
}, []);
return (
<div className="App">
<div className="flex">
<input
onChange={(e) => {
setsearchTerm(e.target.value);
}}
type="text"
placeholder="search"
className="form-control"
style={{
width: "80%",
borderRadius: "30px 0 30px",
justifyContent: "center",
marginLeft: "100px",
}}
/>
<br />
<br />
<form>
<label>first_name</label>
<input value={title} onChange={(e) => setTitle(e.target.value)} />
<label>email</label>
<input value={body} onChange={(e) => setBody(e.target.value)} />
<button onClick={postData}>post</button>
{users
.filter((val) => {
if (searchTerm === "") {
return val;
} else if (
val.first_name.toLowerCase().includes(searchTerm.toLowerCase())
) {
return val;
}
})
.map((datas) => (
<div key={datas.id}>
<p>
<strong>{datas.first_name}</strong>
</p>
<p>{datas.email}</p>
<img key={datas.avatar} src={datas.avatar} />
</div>
))}
</form>
</div>
</div>
);
}

Not getting pre-filled state value from redux when user try to edit the form?

I am trying to get the state from redux store and trying to fill the input field from state. If user in edit mode. In edit mode, we normally show the prefilled value in input field. But what is wrong with the below approach?
I am able to store single user successfully in reducer but in component i am not getting. Sometimes i get the value. Overall, it's very inconsistent.
import React, { useState, useEffect } from "react";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import { useSelector, useDispatch } from "react-redux";
import { useHistory, useParams } from "react-router-dom";
import { addUser, getSingleUser, updateUser } from "../redux/actions";
const useStyles = makeStyles((theme) => ({
root: {
marginTop: 100,
"& > *": {
margin: theme.spacing(1),
width: "45ch",
},
},
}));
const initialState = {
name: "",
address: "",
contact: "",
email: "",
};
const EditUser = () => {
let { id } = useParams();
const { user } = useSelector((state) => state.users);
console.log("user", user);
const [state, setState] = useState(user);
const [error, setError] = useState("");
const { name, address, email, contact } = state;
const classes = useStyles();
const history = useHistory();
let dispatch = useDispatch();
const onInputChange = (e) => {
let { name, value } = e.target;
setState({ ...state, [name]: value });
};
useEffect(() => {
dispatch(getSingleUser(id));
}, []);
const handlSubmit = (e) => {
e.preventDefault();
console.log("name", name);
if (!name || !email || !address || !contact) {
setError("Please fill all Input Field");
} else {
dispatch(updateUser(state, id));
setError("");
history.push("/");
}
};
return (
<>
<Button
style={{ width: "100px", marginTop: "20px" }}
variant="contained"
type="submit"
color="secondary"
onClick={() => history.push("/")}
>
Go Back
</Button>
<h2>Edit user</h2>
{error && <h3 style={{ color: "red" }}>{error}</h3>}
<form
className={classes.root}
noValidate
autoComplete="off"
onSubmit={handlSubmit}
>
<TextField
id="standard-basic"
label="Name"
value={name}
name="name"
onChange={onInputChange}
type="text"
/>
<br />
<TextField
id="standard-basic"
value={email}
name="email"
label="Email"
type="email"
onChange={onInputChange}
/>
<br />
<TextField
id="standard-basic"
value={contact}
name="contact"
label="Contact"
type="number"
onChange={onInputChange}
/>
<br />
<TextField
id="standard-basic"
label="Address"
value={address}
name="address"
type="text "
onChange={onInputChange}
/>
<br />
<Button
style={{ width: "100px" }}
variant="contained"
type="submit"
color="primary"
>
Update
</Button>
</form>
</>
);
};
export default EditUser;
Below is redux actions logic to get the single user and dispatching an action to store single user value in reducer.
export const getSingleUser = (id) => {
return function (dispatch) {
axios
.get(`${process.env.REACT_APP_API}/${id}`)
.then((resp) => {
console.log("resp", resp);
dispatch(singleUser(resp.data));
})
.catch((error) => console.log(error));
};
};

when i click on update button i want the course open in add course with the same values

following is the AddCourse page
AddCourse.js
import React, { useEffect, useState } from 'react';
import { Button, Form, FormGroup, Label, Input, FormText, Container } from 'reactstrap';
import database from '../services/fire';
import { useSelector, useDispatch } from 'react-redux';
import uuid from 'react-uuid';
import '../App.css';
const AddCourse = () => {
const [courseId, setCourseId] = useState('');
const [courseTitle, setCourseTitle] = useState('');
const [courseDesc, setCourseDesc] = useState('');
const dispatch = useDispatch();
const user = useSelector(state => state.auth.user.uid);
useEffect(() => {
document.title = "Add Courses"
}, [])
const addCourse = () => {
const payload = { id: uuid(), courseId:courseId, courseTitle: courseTitle, courseDesc: courseDesc }
const dbcoursesWrapper = database.ref().child(user).child('courses');
// const dbcoursesWrapper = database.ref(`users/${user}/courses`).push(courseId, courseTitle, setCourseDesc);
return dbcoursesWrapper.child(payload.id).update(payload).then(() => {
setCourseId('');
setCourseTitle('');
setCourseDesc('');
dispatch({ type: "ADD_COURSES", payload });
})
}
return (
<div>
<h1 className="text-center my-3">Fill Course Detail</h1>
<Form onSubmit={(e) => {
e.preventDefault(e.target.value);
addCourse();
}}>
<FormGroup>
<label for="UserId">Course Id</label>
<Input
type="text"
value={courseId}
onChange={(e) => setCourseId(e.target.value)}
placeholder="Enter your Id"
name="userId"
id="UserId"
/>
</FormGroup>
<FormGroup>
<label for="title">Course Title</label>
<Input
type="text"
value={courseTitle}
onChange={(e)=> setCourseTitle(e.target.value)}
placeholder="Enter Course Title"
name="title"
id="title"
/>
</FormGroup>
<label for="description">Course Description</label>
<Input
value={courseDesc}
onChange={(e) => setCourseDesc(e.target.value)}
type="textarea"
placeholder="Enter Course Description"
name="description"
id="description"
style={{ height: 150 }}
/>
<Container className="text-center">
<Button color="success" type='submit'>Add Course</Button>
<Button color="warning ml-3">clear</Button>
</Container>
</Form>
</div>
);
};
export default AddCourse;
courses.js here is the update button when i click on it i want it to open the AddCourse page with the same values of the course i want to update not getting any clue how can i do this
import React from 'react';
import {
Card, CardText, CardBody,
CardTitle, Button, Container
} from 'reactstrap';
import database from '../services/fire';
import { useSelector, useDispatch } from 'react-redux';
import { fetchCourse } from '../actions/courses';
import AddCourse from './AddCourse';
const Course = ({course}) => {
const user = useSelector(state => state.auth.user.uid);
const dispatch = useDispatch();
const removeCourse = (id) => {
console.log(id);
const dbtasksWrapper = database.ref().child(user).child('courses');
dbtasksWrapper.child(id).remove().then(() => {
dispatch({ type: 'DELETE_COURSE', id: id })
dispatch(fetchCourse(user));
})
}
return (
<div>
<Card>
<CardBody className="text-center ">
<CardText className="text-center"><h2>CourseID: {course.courseId}</h2></CardText>
<CardTitle className="font-weight-bold text-center"><h1>{course.courseTitle}</h1></CardTitle>
<CardText className="text-center">{course.courseDesc}.</CardText>
<Container className="text-center">
{/* here is the update button and when onclick its goes to add course page with the course vale need to update** */}
<Button color="warning"onClick={}>Update</Button>
<Button color="danger ml-4" onClick={()=>removeCourse(course.id)}>Delete</Button>
</Container>
</CardBody>
</Card>
</div>
);
};
export default Course;
Sorry, not getting your question properly. You are trying to add a course using AddCourse.js component on submitting the form, then you want to display the course ID, Title and Description. In order to do this, you need the following:
1 - localStorage,
2 - Context API or Redux,
3 - Create a new state on your Context API or redux to store the values and pass it down to children components, in your example courses.js
If I understand correctly you want to switch between viewing a course and editing/updating a course?
One way to achieve this is:
const Course = ({ course }) => {
const user = useSelector((state) => state.auth.user.uid);
const dispatch = useDispatch();
const removeCourse = (id) => {
console.log(id);
const dbtasksWrapper = database.ref().child(user).child('courses');
dbtasksWrapper
.child(id)
.remove()
.then(() => {
dispatch({ type: 'DELETE_COURSE', id });
dispatch(fetchCourse(user));
});
};
// state to switch between updating the course and viewing the course
const [isUpdating, setIsUpdating] = useState(false);
return (
<div>
{isUpdating ? (
{/* pass the course down and a callback to close update component */}
<AddCourse course={course} finishUpdate={() => setIsUpdating(false)} />
) : (
<Card>
<CardBody className="text-center ">
<CardText className="text-center">
<h2>CourseID: {course.courseId}</h2>
</CardText>
<CardTitle className="font-weight-bold text-center">
<h1>{course.courseTitle}</h1>
</CardTitle>
<CardText className="text-center">{course.courseDesc}.</CardText>
<Container className="text-center">
{/* Set isUpdating to true */}
<Button color="warning" onClick={() => setIsUpdating(true)}>
Update
</Button>
<Button color="danger ml-4" onClick={() => removeCourse(course.id)}>
Delete
</Button>
</Container>
</CardBody>
</Card>
)}
</div>
);
};
This will change depending on your setup, if this isn't what you wanted please provide some more details about how you would like this to function.

Categories

Resources