pass row values to function in React - reactjs

i am building a table with SQLite Data in React. But i have troubles with passing the [parts] from a specific table row to another function which should show a detail view of the table Row.
This is the table itself:
class Table extends Component {
constructor(props) {
super(props)
this.state = {
parts: [],
isLoading: false,
isError: false,
show: false
}
}
async componentDidMount() {
this.setState({ isLoading: true })
const response = await fetch(`${API_ENDPOINT}/api/bestand`)
if (response.ok) {
const parts = await response.json()
this.setState({ parts, isLoading: false })
} else {
this.setState({ isError: true, isLoading: false })
}
}
render() {
const { parts, isLoading, isError, show } = this.state
if (isLoading) {
return <div>Loading...</div>
}
if (isError) {
return <div>Error</div>
}
if (show === true) {
return this.state.show && this.editSection()
}
return parts.length > 0
? (
<table className="table" id="tblData" >
<thead>
<tr>
<th style={{borderTopLeftRadius: "4px"}}>Teilenummer</th>
<th>Hersteller</th>
<th>Beschreibung</th>
<th>Preis</th>
<th style={{borderTopRightRadius: "4px"}}>SKU</th>
</tr>
</thead>
<tbody>
{this.renderTableRows()}
</tbody>
</table>
) : (
<div>
No parts.
</div>
)
}
renderTableHeader = () => {
return Object.keys(this.state.parts[0]).map(attr =>
<th key={attr} >
{attr}
</th>)
}
renderTableRows = () => {
return this.state.parts.map(part => {
return (
<tr key={part.id} onClick={this.toggle}>
<td>{part.Teilenummer}</td>
<td>{part.Hersteller}</td>
<td>{part.Beschreibung}</td>
<td>{part.Preis}</td>
<td>{part.SKU}</td>
</tr>
)
})
}
with a toggle function i open a view with a form, and all the data from the row i clicked inside as a value.
toggle = () => {
this.setState((currentState) => ({ show: !currentState.show }))
}
detailview:
editSection = () => {
return this.state.parts.map(part => {
return (
<div>
<button className="detailClose" onClick={this.toggle}>✕</button>
<form key={part.id} method="POST">
<div className="Teilenummer">
<label>
Teilenummer:
<br />
<input
type="JSON"
className="teilenrinput"
name="Teilenummer"
id="Teilenummer"
value={part.Teilenummer}
required
/>
<br />
<br />
</label>
</div>
<div className="SKU">
<label>
SKU:
<br />
<input
type="text"
name="SKU"
className="skuinput"
id="SKU"
value={part.SKU}
required
/>
<br />
<br />
</label>
</div>
<div className="Price">
<label>
Preis:
<br />
<input
type="text"
name="Price"
className="priceinput"
id="Preis"
value={part.Preis}
required
/>
<br />
<br />
</label>
</div>
<div className="Hersteller">
<label>
Hersteller:
<br />
<input
list="manufacturers"
name="Hersteller"
id="Hersteller"
className="herstellerinput"
value={part.Hersteller}
required
></input>
<datalist id="manufacturers">
<option value="Volkswagen">Volkswagen</option>
<option value="Audi">Audi</option>
<option value="BMW">BMW</option>
<option value="Mercedes">Mercedes</option>
<option value="Opel">Opel</option>
</datalist>
</label>
</div>
<div className="Beschreibung">
<label>
Beschreibung:
<br />
<input
type="text"
name="Beschreibung"
className="beschreibunginput"
id="Beschreibung"
value={part.Beschreibung}
required
/>
<br />
<br />
</label>
</div>
<input
className="Eintragen-Button"
type="submit"
value="Update "
/>
<span id="response"></span>
<button className="deleteButton" onClick={() => this.deleteTableRow(part.id)}>Delete</button>
</form>
</div>
)
})
}
}
the problem with the current solution is, i map all the data in the editSection function and as a result i render every table row in it, when i click on one row.
how do i map the id´s in a way, that the editSection only renders the row i clicked on in the table?
regards

You need to pass part of parts.map function to the toggle function like
onClick ={part=> this.toggle(part)}.
So than on click event handler you get the row specific value.
Now you can save this part object in state along with show property in toggle function, like
setState({show: someValue, activeRow: part})
Now while loading the form popup or like so, in editSection function use the state.activeRow properly.

Related

Edit Data in Parent from Child

Apparently I'm not doing this right, but I'm trying to mutate a map in the parent component from a child component in React 18.2. The parent contains a modal which opens a form. The user then inputs their mutate option (delete/add) and subsequent data from there. I've been going through other questions trying to find an answer for why it's not working as intended, but I can't seem to find much info. Would appreciate any help. This is what I currently have:
Parent.Js
const ParentComponent = ({show, onCloseModalButton}) => {
const resorts = new Map()
resorts.set("Keystone", [39.6069742, -105.97011])
resorts.set("Breckenridge", [39.4808, -106.0676])
resorts.set("Vail", [39.6061, -106.3550])
resorts.set("Crested Butte", [38.8991, -106.9658])
resorts.set("Winter Park", [39.8841, -105.7627])
resorts.set("Copper Mountain", [39.5022, -106.1497])
const [formOption, setFormOption] = React.useState("")
const [formData, setFormData] = React.useState({
resortName: "",
longitude: Number,
latitude: Number,
})
const handleOptionChange = e => {
setFormOption(e.target.value)
}
const handleFormDataChange = e => {
setFormData({
...formData,
[e.target.name]: e.target.value,
})
}
const submitForm = e => {
e.preventDefault()
if (formOption === "Add") {
resorts.set(formData.resortName, [formData.latitude, formData.longitude])
}
if (formOption === "Delete") {
resorts.delete(formData.resortName)
}
}
return (
<div>
<Modal show={show} onCloseModalButton={onCloseModalButton} resorts={resorts} submitForm={submitForm} handleOptionChange={handleOptionChange} handleFormChange={handleFormDataChange} option={formOption} form={formData} />
</div>
)
}
export default ParentComponent;
Modal.js
const Modal = ({show, onCloseModalButton, resorts, submitForm, handleOptionChange, handleFormChange, option, form}) => {
if (!show) {
return null
}
return ReactDOM.createPortal (
<div className='modal-bg'>
<div className='modal'>
<form onSubmit={submitForm}>
<label>Modify:
<select
name="option"
value={option}
onChange={handleOptionChange}
>
<option value="" disabled={true}>-- Choose an Option --</option>
<option value="Add">Add</option>
<option value="Delete">Delete</option>
</select>
</label>
{option === "" ? null :
option === "Add" ?
<div>
<label>Resort Name
<input
type="text"
name="resortName"
value={form.resortName}
onChange={handleFormChange}
/>
</label>
<br></br>
<label>Longitude
<input
type="number"
name="longitude"
value={form.longitude}
onChange={handleFormChange}
/>
</label>
<br></br>
<label>Latitude
<input
type="number"
name="latitude"
value={form.latitude}
onChange={handleFormChange}
/>
</label>
<button type='submit'>Submit</button>
</div> :
<div>
<label>Delete
<select
name="delete"
value={form.resortName}
onChange={handleFormChange}
>
{[...resorts.keys()].map((item)=> {
return <option key={item} value={item}>{item}</option>
})}
</select>
</label>
<button type='submit'>Submit</button>
</div>
}
</form>
<button onClick={onCloseModalButton}>Close Modal</button>
</div>
</div>
, document.body
)
}
export default Modal;

How to validate a table with arrays using SimpleReactValidator

I have a table that can add and delete rows. However, am not able to validate the table. if the table cells are empty or filled am not able to post the values to the backend. The error message still shows.What is the best way to validate the table. I would like to have the error message show if the fields are empty on submit.
payment.js
import React, {Component } from "react";
import "bootstrap/dist/css/bootstrap.min.css"
import axios from "axios"
import SimpleReactValidator from "simple-react-validator"
import Box from '#mui/material/Box';
import Button from "#mui/material/Button";
import BillTable from "./billTable"
import $ from 'jquery'
class Payment extends Component {
constructor(){
super()
this.state = {
Bill:"",
billTable: [{
index: Math.random(),
serialNumber: "",
item:"",
cost:""}],
errorMessage: '',
}
this.validator = new SimpleReactValidator({autoForceUpdate: this,messages: {
default: 'Please enter this field!'
},element: message => <div style={{color: "red"}}>{message}</div>})
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleChange = (e) => {
if (["serialNumber", "item", "cost"].includes(e.target.name)) {
let billTable = [...this.state.billTable]
billTable[e.target.dataset.id][e.target.name] = e.target.value;
}
else {
this.setState({ [e.target.name]: e.target.value })
}
};
addNewRowPlan = () => {
this.setState((prevState) => ({
billTable: [...prevState.billTable, { index: Math.random(), serialNumber: "", item: "", cost:""}],
}));
}
deleteRow = (index) => {
this.setState({
billTable: this.state.billTable.filter((s, sindex) => index !== sindex),
});
}
clickOnDelete(record) {
this.setState({
billTable: this.state.billTable.filter(r => r !== record),
});
}
handleSubmit(event){
event.preventDefault()
if(this.validator.allValid()){
this.validator.hideMessages()
const billed = {
Bill:this.state.billTable
};
axios.post(`http://localhost:4000/bill`, billed,{
})
.then(response => {
console.log(response.data)
return $('.alert-success').show();
})
this.setState({
Bill:"",
})
}
else{
this.validator.showMessages()
this.forceUpdate()
return $('.alert-danger').show();
}
}
render() {
let {billTable} = this.state
return (
<div>
<div className="container">
<div className="form-div">
<h1>Billing</h1>
<Box component="form" onSubmit={this.handleSubmit} noValidate sx={{ mt: 1}} onChange={this.handleChange}>
<div className="row" style={{ marginTop: 20 }}>
<div className="col-sm-3"></div>
<div className="col-sm-12">
<div className="card">
<div className="card-header text-center">Bill</div>
<div className="card-body">
<div className="row">
<div className="col-sm-4">
</div>
</div>
<table>
<thead>
<tr>
<th>Serial #</th>
<th>Item</th>
<th>Cost</th>
</tr>
</thead>
<tbody>
<BillTable id="bill" add={this.addNewRowPlan.bind(this)} delete={this.clickOnDelete.bind(this)} billTable={billTable} />
{this.validator.message('bill',this.state.Bill,'required')}
</tbody>
</table>
</div>
</div>
</div>
<div className="col-sm-1"></div>
</div>
<Button
type="submit"
fullWidth
sx={{ mt: 3, mb: 2}}
>
<span>Submit</span>
</Button>
</Box>
</div>
</div>
</div>
);
}
}
export default Payment;
billTable.js
import React from "react"
const billTable = (props) => {
return (props.billTable.map((val, idx) => {
let serialNumber = `serialNumber-$${idx}`, item = `item-$${idx}`, cost = `cost-$${idx}`
return (
<tr key={val.index}>
<td>
<input type="text" name="serialNumber" data-id={idx} id={serialNumber} className="form-control" />
</td>
<td>
<input type="text" name="item" data-id={idx} id={item} className="form-control " />
</td>
<td>
<input type="text" name="cost" data-id={idx} id={cost} className="form-control"/>
</td>
<td>
{
idx===0?<button onClick={()=>props.add(idx)} type="button" className="btn btn-primary">Add Row</button>
: <button className="btn btn-danger" onClick={(() => props.delete(val))} >Delete Row</button>
}
</td>
</tr>
)
})
)
}
export default billTable
`````````````````````
How can i correct this code. Thank you in advance

How to pass a prop through history.push() in react?

I have a login component that has an email and password to log in. After a successful, I use this.props.history.push('/userComponent) to route a another component. At the component where it is routed should display the name of the person/user. I am trying to send as a prop but I end up getting undefined as the user component (the component to which it is routed) is not rendered. Please check the below.
export default class Login extends Component {
constructor(props) {
super(props);
this.x = '';
}
onSubmit = () => {
fetch('http://localhost:5000/api/account/')
.then(res => res.json())
.then(data => {
for (let index = 0; index < data.length; index++) {
if (userName === data[index].email && passWord === data[index].password && data[index].role === "Admin") {
console.log("login is successful");
this.x = true;
console.log('.......state after update: ' + this.x);
this.props.history.push('/userA');
return (
<div>
<UserA somePropName={data[index].userName} />
</div>
);
}
else if (userName === data[index].email && passWord === data[index].password) {
console.log("login is successful");
this.x = false;
console.log("x....... " + this.x);
this.props.history.push('/userB');
return (
<UserB somePropName={data[index].userName} />
);
}
else {
this.props.history.push('/errorPage');
}
}
});
}
render() {
return (
<div>
<div class="container">
<label for="uname"><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="uname" required />
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="psw" required />
<button type="submit" onClick={this.onSubmit}>Login </button>
<label>
<input type="checkbox" checked="checked" name="remember" /> Remember me
</label>
</div>
<div class="container" style="background-color:#f1f1f1">
<button type="button" class="cancelbtn">Cancel</button>
<span class="psw">Forgot password?</span>
</div>
</div>
);
}
}
The way you can pass properties to other component while navigation
this.props.history.push({
pathname: '/userB',
state: { title: 'Hello world' }
})
using Link
<Link to={{
pathname: '/userB',
state: { title: 'Hello...' }
}}>Click</Link>
Access like this in navigated component
this.props.location.state.title
You should render conditionally UserA or UserB in render(). Place the user related fields in the state. Something like
render() {
return (
<div>
<div class="container">
<label for="uname"><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="uname" required />
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="psw" required />
<button type="submit" onClick={this.onSubmit}>Login </button>
<label>
<input type="checkbox" checked="checked" name="remember" /> Remember me
</label>
</div>
<div class="container" style="background-color:#f1f1f1">
<button type="button" class="cancelbtn">Cancel</button>
<span class="psw">Forgot password?</span>
</div>
{this.state.isLoggedIn && this.state.isAdmin && <UserA somePropName={this.state.userName} />}
{this.state.isLoggedIn && !this.state.isAdmin && <UserB somePropName={this.state.userName} />}
</div>);
}
For the onSubmit func
onSubmit = () => {
fetch('http://localhost:5000/api/account/')
.then(res => res.json())
.then(data => {
this.props.history.push('/xxx');
this.setState({
isAdmin: data[index].role === "Admin"
isLoggedIn: userName === data[index].email && passWord === data[index].password,
userName: data[index].userName
})
})
}

Cannot able to Access Data passed as argument from one component to another in ReactJs

In my scenario, I have two components ListEnterprise and AddEnterprise. On clicking the update button I need to access and send the particular Id of Enterprise to AddEnterprise(we are using same component for adding and updating the records). How to access the EnterpriseId in AddEnterprise component? Thanks in advance.
ListEnterprise
class ListEnterprises extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
enterprises: [],
message: null,
showFormMessage: false,
showUpdateForm: false,
}
//Any method in a react component should be bound to this
this.refreshEnterprises = this.refreshEnterprises.bind(this);
this.editEnterprise = this.editEnterprise.bind(this);
}
// After all the elements of the page is rendered correctly, this method is called.
// After the markup is set on the page, this technique called by React itself to either fetch the data from An External API or perform some unique operations which need the JSX.API
// componentDidMount() method is the perfect place, where we can call the setState() method to change the state of our application and render() the updated data loaded JSX. For example, we are going to fetch any data from an API then API call should be placed in this lifecycle method,
// and then we get the response, we can call the setState() method and render the element with updated data.
//React defines a component lifecycle. componentDidMount will be called as soon as the component is mounted. We are calling refreshCourses as soon as a component is mounted.
componentDidMount() {
this.refreshEnterprises();
}
_showMessage = (bool, update = false) => {
this.setState({
showFormMessage: bool,
showUpdateForm: false,
});
if (update) {
this.refreshEnterprises();
}
}
refreshEnterprises() {
EnterpriseService.retrieveAllEnterprises()
.then((response) => {
console.log(response.data);
this.setState({ enterprises: response.data, isLoading: false });
}).catch((error) => {
console.log(error);
});
}
// removeEnterprise(id) {
// EnterpriseService.deleteEnterprise(id)
// .then((response) => {
// console.log(response.data);
// let updatedEnterprises = [...this.state.enterprises].filter(i => i.id !== id);
// this.setState({ enterprises: updatedEnterprises });
// }).catch((error) => {
// console.log(error);
// });
// }
editEnterprise(enterpriseId) {
this._showMessage.bind(null, false);
this.setState({ showUpdateForm: true, showFormMessage: false });
return enterpriseId;
}
render() {
console.log("Rendering Enterprises");
if (this.state.showUpdateForm)
let recordId = this.editEnterprise;
if (this.state.isLoading)
return (<div>Loading...</div>);
return (
<div key={this.props.location.pathname}>
<NavigationComponent /><br /><br />
<h3 align="center">Here are all your Enterprises</h3><br />
{this.state.message && <div class="alert alert-success">{this.state.message}</div>}
<Container>
<Table striped bordered hover size="sm">
<thead>
<tr>
<th>Enterprise</th>
<th>Industry</th>
<th>Business Units</th>
<th>Description</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{
this.state.enterprises.map(
enterprise =>
<tr key={enterprise.id}>
<td>{enterprise.enterpriseName}</td>
<td>{enterprise.industry}</td>
<td>
{enterprise.businessUnits.map(bu =>
<td>{bu.businessUnitName}</td>
)}
</td>
<td>{enterprise.description}</td>
<td><button className="btn btn-warning" onClick={() => this.editEnterprise(enterprise.id)}>Update</button></td>
<td><button className="btn btn-danger" onClick={() => this.removeEnterprise(enterprise.id)}>Delete</button></td>
</tr>
)
}
</tbody>
</Table>
</Container>{" "}{" "}{" "}
<div className="container">
<Button color="primary" size="lg" onClick={this._showMessage.bind(null, true)}>Add Enterprise</Button>{' '}
<Button color="secondary" size="lg" onClick={this._showMessage.bind(null, false)}>Hide</Button>{' '}
{(this.state.showFormMessage && <AddEnterprise showMessage={this._showMessage} {...this.props} />)}
{(this.state.showUpdateForm && <AddEnterprise editEnterprise={this.editEnterprise} showUpdateForm={this.state.showUpdateForm} showMessage={this._showMessage} {...this.props} />)}
</div>
<br /><br />
<FooterComponent />
</div >
);
}
}
export default ListEnterprises;
AddEnterprise(Same component is Using to Update as well)
class AddEnterprise extends Component {
emptyEnterprise = {
enterpriseName: "",
industry: "",
description: "",
businessUnits: ""
};
constructor(props) {
super(props);
this.state = {
isLoading: true,
isForm: false,
enterprisePayload: this.emptyEnterprise
}
this.handleChange = this.handleChange.bind(this);
this.addEnterprise = this.addEnterprise.bind(this);
this.editEnterprise = this.editEnterprise.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
let updatedEnterprisePayload = { ...this.state.enterprisePayload };
updatedEnterprisePayload[name] = value;
this.setState({ enterprisePayload: updatedEnterprisePayload });
console.log(updatedEnterprisePayload);
}
editEnterprise() {
this.props.editEnterprise();
}
addEnterprise(event) {
var obj = [];
const businessUnitsData = this.state.enterprisePayload.businessUnits.split(",");
console.log(businessUnitsData);
businessUnitsData.map(x => {
let objVar = new BusinessUnit("", x);
console.log(objVar);
obj.push(objVar);
});
console.log(obj);
let updatedPayload = this.state.enterprisePayload;
updatedPayload["businessUnits"] = obj;
this.setState({ enterprisePayload: updatedPayload });
const payload = this.state.enterprisePayload;
EnterpriseService.addEnterprise(payload)
.then((response) => {
this.setState({ isLoading: false, isForm: true });
this.props.showMessage(false, true); //In React we use state for things like these, you can't always redirect
})
.catch((error) => {
console.log(error);
});
}
render() {
if (this.state.isLoading && this.state.isForm)
return (<div>Loading...</div>);
return (
<div className="base-container">
{!this.props.showUpdateForm && <div className="header"><div><br />Add Enterprise</div></div>}
{this.props.showUpdateForm && <div className="header"><div><br />Update Enterprise</div></div>}
<div className="content">
<div className="form">
<div className="form-group">
<label htmlFor="enterpriseName" for="enterpriseName">Enterprise Name</label>
<input type="text" name="enterpriseName" id="enterpriseName" placeholder="enterpriseName" onChange={this.handleChange} />
</div>
<div className="form-group">
<label htmlFor="industry" for="industry">Industry</label>
<input type="text" name="industry" id="industry" placeholder="industry" onChange={this.handleChange} />
</div>
<div className="form-group">
<label htmlFor="businessUnits" for="businessUnits">Business Units</label>
<input type="text" name="businessUnits" id="businessUnits" placeholder="businessUnits" onChange={this.handleChange} />
</div>
<div className="form-group">
<label htmlFor="description" for="description">Description</label>
<input type="text" name="description" id="description" placeholder="description" onChange={this.handleChange} />
</div>
</div>
</div>
<div className="footer">
{!this.props.showUpdateForm && <button type="button" className="btn" onClick={this.addEnterprise}>Add</button>}
{this.props.showUpdateForm && <button type="button" className="btn" onClick={this.editEnterprise}>Update</button>}
</div>
</div>
);
}
}
export default AddEnterprise;

React component is not re-rendered after the state is changed with a dropdown list [react hooks]

I have the following React component (using hooks), which lists a number of Tasks as a dropdown list. When an item is selected from the list, I want to display an Update form. This works only when an item is selected for the first time. When I select a new item, nothing happens (although console.log(e.target.value); prints the correct value). I store the selected task's id in st_taskId.
I wonder if you see any issues in the code below:
const ManageReviewTasks = props => {
const reviewRoundId = props.match.params.reviewRoundId;
const [st_taskId, set_taskId] = useState();
useEffect(() => {
if (props.loading == false && st_taskId == null)
props.fetchReviewTasksByReviewRound(reviewRoundId);
}, [reviewRoundId, st_taskId]);
if (props.loading == true) {
return <div>Loading...</div>;
}
return (
<>
{props.reviewTasks && (
<div>
<h3>Configure the Review Tasks</h3>
<br />
{
<div>
<div>
<h4>
Tasks for <span className="font-italic">students receiving</span> feedback:
</h4>
<select
className="form-control"
onChange={e => {
e.preventDefault();
console.log(e.target.value);
set_taskId(e.target.value);
}}>
<option>--SELECT--</option>
{Object.keys(props.reviewTasks).map(id => {
const task = props.reviewTasks[id];
{
if (task.isForStudent) {
return (
<option key={id} id={id} value={id}>
{task.title}
</option>
);
}
}
})}
</select>
</div>
{props.reviewTasks[st_taskId] && (
<UpdateReviewTaskForm task={props.reviewTasks[st_taskId]} />
)}
</div>
}
</div>
)}
</>
);
};
Below is the code for the UpdateReviewTaskForm component:
const UpdateReviewTaskForm = (props) => {
const [st_Title, set_Title] = useState(props.task.title);
const [st_Description, set_Description] = useState(RichTextEditor.createValueFromString(props.task.description, 'html'));
const [st_startDate, set_startDate] = useState(new Date(props.task.startDate.replace('-', '/')));
const [st_DueDate, set_DueDate] = useState(new Date(props.task.dueDate.replace('-', '/')));
const handleCancelClick = (event) => {
event.preventDefault();
history.goBack();
}
const onSubmit_saveTask = (e) => {
e.preventDefault();
props.updateReviewTask({
Id: props.task.id,
Title: st_Title,
Description: st_Description.toString('html'),
StartDate: format(st_startDate, 'DD/MM/YYYY'),
DueDate: format(st_DueDate, 'DD/MM/YYYY'),
})
}
if (props.loading)
return <div>Updating...</div>
return (
<div>
<br/>
<br/>
<div className="p-3 bg-light">
<h3 className="text-info">Update the Task:</h3>
{
props.task &&
<form onSubmit={onSubmit_saveTask}>
<div className="form-group">
<label>Enter the title</label>
<input
//placeholder="Enter a title..."
value={st_Title}
onChange={(event) => { set_Title(event.target.value) }}
className="form-control" />
</div>
<div className="form-group">
<label>Enter a description for the assessment</label>
<RichTextEditor
value={st_Description}
onChange={set_Description}
/>
</div>
<div className="form-group">
<label>Start date to start: </label>
<DatePicker
className="form-control"
selected={st_startDate}
onChange={(date) => set_startDate(date)}
/>
</div>
<div className="form-group">
<label>Due date to complete: </label>
<DatePicker
className="form-control"
selected={st_DueDate}
onChange={(date) => set_DueDate(date)}
/>
</div>
<br />
<button type="submit" className="btn btn-primary">Submit</button>
<button type="reset" className="btn btn-light" onClick={handleCancelClick}>Cancel</button>
</form>
}
</div>
</div>
)
}
Because you are using internal state in UpdateReviewTaskForm, even if this component re-render for the second time, its state will not be reset (to the default value props.task.title for example).
One way to force the state to reset is to use a key prop in UpdateReviewTaskForm like this :
{props.reviewTasks[st_taskId] && (
<UpdateReviewTaskForm key={st_taskId} task={props.reviewTasks[st_taskId]} />
)}
Another way is to use useEffect inside UpdateReviewTaskForm to run when props.task change
useEffect(() => {
// reset the state here
}, [props.task])

Resources