In ReactJS, in my child ponent, onChange() event on a input > text just takes one value and not retaining previous values on every keypress.
I am trying to capture the inputs in a child form and wants to transfer it to parent. Actually I am trying to reuse the child form for Create & Edit pages.
My full codesandbox is here
Child Component
import React, { Component } from "react";
import { Form } from "react-bootstrap";
export default class EmployeeForm extends Component {
constructor(props) {
super(props);
console.log("this.props.employee ", this.props.employee);
}
/** Generic handle change events for all fields */
handleChange = e => {
this.props.employee[e.target.id] = e.target.value;
console.log(e.target.value);
};
// handleChange = (key, e) => {
// e.preventDefault();
// console.log(key);
// console.log(e.target.value);
// this.props.employee[key] = e.target.value;
// };
render() {
const { employee } = this.props;
console.log("ef render ", employee.firstName);
return (
<div>
<Form.Group controlId="firstName">
<Form.Label>First name</Form.Label>
<Form.Control
type="text"
value={employee.firstName}
onChange={this.handleChange}
placeholder="Enter first name"
/>
</Form.Group>
<Form.Group controlId="lastname">
<Form.Label>Last name</Form.Label>
<Form.Control
type="text"
value={employee.lastName}
onChange={this.handleChange}
placeholder="Enter last name"
/>
</Form.Group>
<Form.Group controlId="birthDate">
<Form.Label>Date of birth</Form.Label>
<Form.Control
type="date"
value={employee.birthDate}
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId="hireDate">
<Form.Label>Date of hire</Form.Label>
<Form.Control
type="date"
value={employee.hireDate}
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId="gender">
<Form.Label>Gender</Form.Label>
<Form.Control
as="select"
value={employee.gender}
onChange={this.handleChange}
>
<option value="">Please select</option>
<option value="F">Female</option>
<option value="M">Male</option>
</Form.Control>
</Form.Group>
</div>
);
}
}
Parent Component
import React from "react";
import { Alert, Form, Col, Row, Button, Card } from "react-bootstrap";
import EmployeeForm from "./EmployeeForm";
import EmployeeService from "./services/EmployeeService";
export default class CreateEmployee extends React.Component {
constructor() {
super();
this.employeeService = new EmployeeService();
this.state = {
employee: {
firstName: "",
lastName: "",
birthDate: "",
hireDate: "",
gender: ""
}
};
}
save = () => {
console.log(this.state.values);
this.employeeService
.createEmployee(this.state.values)
.then(result => {
this.setState({ error: null });
})
.catch(err => {
console.log(err);
this.setState({ error: err });
});
};
render() {
console.log("reder : ", this.state.employee);
return (
<div>
<Form>
<Alert variant="primary">Employee</Alert>
<Card style={{ width: "500px" }}>
<Card.Header>Create Employee</Card.Header>
<Card.Body>
<EmployeeForm employee={this.state.employee} />
<Row>
<Col>
<Button variant="primary" type="button" onClick={this.save}>
Create
</Button>
</Col>
</Row>
</Card.Body>
</Card>
</Form>
</div>
);
}
}
In ReactJS, in my child ponent, onChange() event on a input > text just takes one value and not retaining previous values on every keypress.
I am trying to capture the inputs in a child form and wants to transfer it to parent. Actually I am trying to reuse the child form for Create & Edit pages.
My full codesandbox is here https://codesandbox.io/embed/sleepy-stallman-fbyhh?fontsize=14
Child Component
import React, { Component } from "react";
import { Form } from "react-bootstrap";
export default class EmployeeForm extends Component {
constructor(props) {
super(props);
console.log("this.props.employee ", this.props.employee);
}
/** Generic handle change events for all fields */
handleChange = e => {
this.props.employee[e.target.id] = e.target.value;
console.log(e.target.value);
};
// handleChange = (key, e) => {
// e.preventDefault();
// console.log(key);
// console.log(e.target.value);
// this.props.employee[key] = e.target.value;
// };
render() {
const { employee } = this.props;
console.log("ef render ", employee.firstName);
return (
<div>
<Form.Group controlId="firstName">
<Form.Label>First name</Form.Label>
<Form.Control
type="text"
value={employee.firstName}
onChange={this.handleChange}
placeholder="Enter first name"
/>
</Form.Group>
<Form.Group controlId="lastname">
<Form.Label>Last name</Form.Label>
<Form.Control
type="text"
value={employee.lastName}
onChange={this.handleChange}
placeholder="Enter last name"
/>
</Form.Group>
<Form.Group controlId="birthDate">
<Form.Label>Date of birth</Form.Label>
<Form.Control
type="date"
value={employee.birthDate}
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId="hireDate">
<Form.Label>Date of hire</Form.Label>
<Form.Control
type="date"
value={employee.hireDate}
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId="gender">
<Form.Label>Gender</Form.Label>
<Form.Control
as="select"
value={employee.gender}
onChange={this.handleChange}
>
<option value="">Please select</option>
<option value="F">Female</option>
<option value="M">Male</option>
</Form.Control>
</Form.Group>
</div>
);
}
}
Parent Component
import React from "react";
import { Alert, Form, Col, Row, Button, Card } from "react-bootstrap";
import EmployeeForm from "./EmployeeForm";
import EmployeeService from "./services/EmployeeService";
export default class CreateEmployee extends React.Component {
constructor() {
super();
this.employeeService = new EmployeeService();
this.state = {
employee: {
firstName: "",
lastName: "",
birthDate: "",
hireDate: "",
gender: ""
}
};
}
save = () => {
console.log(this.state.values);
this.employeeService
.createEmployee(this.state.values)
.then(result => {
this.setState({ error: null });
})
.catch(err => {
console.log(err);
this.setState({ error: err });
});
};
render() {
console.log("reder : ", this.state.employee);
return (
<div>
<Form>
<Alert variant="primary">Employee</Alert>
<Card style={{ width: "500px" }}>
<Card.Header>Create Employee</Card.Header>
<Card.Body>
<EmployeeForm employee={this.state.employee} />
<Row>
<Col>
<Button variant="primary" type="button" onClick={this.save}>
Create
</Button>
</Col>
</Row>
</Card.Body>
</Card>
</Form>
</div>
);
}
}
Share
Improve this question
edited Sep 14, 2019 at 17:48
Jay
asked Sep 14, 2019 at 17:32
JayJay
9,50914 gold badges62 silver badges100 bronze badges
2
-
2
You are mutating state:
this.props.employee[e.target.id] = e.target.value;
pass a change function from parent to child that does a setState without mutating. – HMR Commented Sep 14, 2019 at 17:34 - Thanks, its actual child to parent munication. Once the user enters all data in the child form I want to transfer to the parent. – Jay Commented Sep 14, 2019 at 17:40
3 Answers
Reset to default 2So I went through the code on codesandbox and made the following changes - the obvious changes have ments on-top: You can check them out here - https://codesandbox.io/s/react-parent-child-1fif1?fontsize=14
You should not do the following:
Mutate state directly
Try to mutate a state in a parent ponent from child ponent's props
EmployeeForm.js - Child ponent
import React, { Component } from "react";
import { Form } from "react-bootstrap";
export default class EmployeeForm extends Component {
constructor(props) {
super(props);
}
// create a handleChangle method here, that calls the handleChange from props
// So you can update the state in CreateEmployee with values from the form
handleChange = e => {
this.props.handleChange(e)
};
render() {
const { employee } = this.props;
// console.log("ef render ", employee.firstName);
return (
<div>
<Form.Group controlId="firstName">
<Form.Label>First name</Form.Label>
<Form.Control
type="text"
value={employee.firstName}
onChange={this.handleChange}
placeholder="Enter first name"
/>
</Form.Group>
<Form.Group controlId="lastName">
<Form.Label>Last name</Form.Label>
<Form.Control
type="text"
value={employee.lastName}
onChange={this.handleChange}
placeholder="Enter last name"
/>
</Form.Group>
<Form.Group controlId="birthDate">
<Form.Label>Date of birth</Form.Label>
<Form.Control
type="date"
value={employee.birthDate}
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId="hireDate">
<Form.Label>Date of hire</Form.Label>
<Form.Control
type="date"
value={employee.hireDate}
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId="gender">
<Form.Label>Gender</Form.Label>
<Form.Control
as="select"
value={employee.gender}
onChange={this.handleChange}
>
<option value="">Please select</option>
<option value="F">Female</option>
<option value="M">Male</option>
</Form.Control>
</Form.Group>
</div>
);
}
}
CreateEmployee.js - Parent ponent
import React from "react";
import { Alert, Form, Col, Row, Button, Card } from "react-bootstrap";
import EmployeeForm from "./EmployeeForm";
import EmployeeService from "./services/EmployeeService";
export default class CreateEmployee extends React.Component {
constructor() {
super();
this.employeeService = new EmployeeService();
this.state = {
employee: {
firstName: "",
lastName: "",
birthDate: "",
hireDate: "",
gender: ""
}
};
}
// Create handleChange here and pass it to EmployeeForm as props
// Use setState instead of mutating state
handleChange = e => {
this.setState({employee: {[e.target.id]: e.target.value}})
};
save = () => {
console.log(this.state.values);
this.employeeService
.createEmployee(this.state.values)
.then(result => {
this.setState({ error: null });
})
.catch(err => {
console.log(err);
this.setState({ error: err });
});
};
render() {
console.log("reder : ", this.state.employee);
return (
<div>
<Form>
<Alert variant="primary">Employee</Alert>
<Card style={{ width: "500px" }}>
<Card.Header>Create Employee</Card.Header>
<Card.Body>
<EmployeeForm handleChange={this.handleChange} employee={this.state.employee} />
<Row>
<Col>
<Button variant="primary" type="button" onClick={this.save}>
Create
</Button>
</Col>
</Row>
</Card.Body>
</Card>
</Form>
</div>
);
}
}
Note: I only fixed errors that was required by this question - you might still need to refactor some part of your codes. Don't forget not to mutate the state directly.
Your problem is that you have state in your Parent
ponent, and you need to change state in your Parent
ponent from a Child
ponent. In order to achieve this you need to create handlechange
method in your Parent
ponent that changes your state and send it with props to your Child
ponent.
Here is an example of how you could pass a function from Parent to Child that will use setState to set the state in Parent.
The Parent is a class and the Child is a functional ponent there are no optimizations (you can prevent creating a new reference for the callback function but that would make the example more plicated):
export default class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
employee: {
firstName: '',
lastName: '',
birthDate: '',
hireDate: '',
gender: '',
},
};
}
inputs = ['lastName'];
render() {
return (
<div>
{this.inputs.map(key => (
<Child
key={key}
//value from this.state
value={this.state.employee[key]}
//will set this.state with value passed
change={val =>
this.setState({
...this.state,
employee: {
...this.state.employee,
[key]: val,
},
})
}
/>
))}
</div>
);
}
}
const Child = ({ change, value }) => {
const onChange e => change(e.target.value);
return (
<input type="text" onChange={onChange} value={value} />
);
};
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742415925a4439741.html
评论列表(0条)