React: Input field doesn't receive input - reactjs

I tried to type in form input field, but its not working. Currently its in readonly mode, I am not sure why . Here is the component :
import React from 'react';
export default class SearchBar extends React.Component {
constructor(props) {
super(props);
this.state = { term: ''};
this.onInputChange = this.onInputChange.bind(this);
}
onInputChange(event) {
console.log(event.target.value);
this.setState({ term: event.target.value});
}
render() {
return (
<form className="input-group">
<input
placeholder="Give a five day forecast"
className="form-control"
value={this.state.term}
onChange={this.noInputChange}
/>
<span className="input-group-btn">
<button type="submit" className="btn btn-secondary"> Submit</button>
</span>
</form>
)
}
}

onChange={this.noInputChange}
should be
onChange={this.onInputChange}

Related

How to invoke a component on handleSubmit in react

I am learning react. I have created a form and on submit I want to render another(Info here) component and I am unable to do so.here is my code example.
App.js
class App extends React.Component {
constructor(props) {
super(props)
this.state = { username: '' }
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event) {
this.setState({ value: event.target.value })
}
handleSubmit(event) {
alert(this.state.username)
event.preventDefault()
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
<button type="button" class ="button" value="Info" onClick={this.handleSubmit} component = {Summary}>Summary</button>
</form>
)
}
}
Info.js
class Info extends React.Component{
{more logic and code for this component}
render(){
return (<h1>Welcome To Info</h1>)
}
}
export default Info
You can do it this way
class App extends React.Component {
constructor(props) {
super(props)
this.state = { username: '', showInfo: false }
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event) {
this.setState({ value: event.target.value })
}
handleSubmit(event) {
alert(this.state.username)
event.preventDefault()
this.setState({showInfo: true});
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
<button type="button" class ="button" value="Info" onClick={this.handleSubmit} component = {Summary}>Summary</button>
</form>
{this.state.showInfo ? <Info /> : null}
</div>
)
}
}
function Info(props){
return <h3>{props.username}</h3>
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = { username: '' }
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange =(event)=> {
this.setState({ username: event.target.value })
}
handleSubmit(event) {
alert(this.state.username)
event.preventDefault()
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
<button type="button" class ="button" value="Info"
onClick={this.handleSubmit}>Summary</button>
</form>
<Info {...this.state}/>
</div>
)
}
}

How to pass Child Component's form value to Parent Component

Is there a way to pass form data from child component to Parent component, where submit buttons have been kept in parent component.
NOTE: - I don't want to use ref for this as the ref would be waste of so much of memory and I might have 6-7 children in the parent.
I have created a similar situation to show what I am stuck on.
class FirstChildForm extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
render() {
return (
<div className="form">
<input type="text" placeholder="Enter your name..." />
<input type="password" placeholder="Enter password" />
</div>
)
}
}
class SecondChildForm extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
render() {
return (
<div className="form">
<input type="text" placeholder="Enter your name..." />
<input type="password" placeholder="Enter password" />
</div>
);
}
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
handleSubmit = () => {
}
render() {
return (
<div className="parent">
<FirstChildForm />
<SecondChildForm />
<button onClick={this.handleSubmit}> Submit</button>
</div>
)
}
}
Sure, the concept is called lifting the state up. Basically, your <App /> component would hold the data from both components. I'm going to simplify a bit, but you should understand what I'm doing.
FirstChildForm.js
<input type="text" name="username" onChange={e => props.updateData('user', e.target.value)}
SecondChildForm.js
<input type="password" name="password" onChange={e => props.updateData('pass', e.target.value)}
App.js
export default class App extends React.Component {
constructor() {
super();
this.state = {
user: '',
pass: '',
};
}
handleSubmit = () => {};
updateData = (target, value) => {
this.setState({ [target]: value });
};
render() {
return (
<div className="parent">
<FirstChildForm updateData={this.updateData} />
<SecondChildForm updateData={this.updateData} />
<button onClick={this.handleSubmit}> Submit</button>
</div>
);
}
}
The <App /> component is the source of truth. Please note:
By lifting the state up, <FirstChildForm /> and <SecondChildForm /> don't need to be class based components anymore, they can be functional components. If you want them to remain class based for whatever reason, change props.updateData to this.props.updateData, else it won't work.
The parent is where we define the function, the child is where we execute it, sending data to parent, basically!
by passing a function to the child component as props and passing the child component's state as parameter to the function
as i dont know what you exactly want to code inside but only to understand checkout
following example
parent:
export default class App extends React.Component {
constructor(props){
super(props);
this.state = {
data: []
}
}
handleSubmit = () => {
}
handleData = (newData) => {
this.setState({data: newData});
}
render(){
return (
<div className="parent">
<FirstChildForm / >
<SecondChildForm onSelectData={this.handleData}/>
<button onClick={this.handleSubmit}> Submit</button>
</div>
)
}
}
Child:
class SecondChildForm extends React.Component{
constructor(props){
super(props);
this.state = {
data:'hello'
}
}
handleDataChange: function () {
var newData = this.state.data
this.props.onSelectData(newData);
},
render(){
return (
<div className="form">
<input type="text" placeholder="Enter your name..." />
<input type="password" placeholder="Enter password" />
<button onclick={this.handleDataChange}>submit</button>
</div>
);
}
}
You will have to pass a function down to your children components. Your children will now be able to bind this function from their props to the given fields.
class FirstChildForm extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
render() {
return (
<div className="form">
<input type="text" placeholder="Enter your name..." onChange={this.props.dataChanged('name')}/>
<input type="password" placeholder="Enter password" onChange={this.props.dataChanged('password')}/>
</div>
)
}
}
class SecondChildForm extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
render() {
return (
<div className="form">
<input type="text" placeholder="Enter your name..." onChange={this.props.dataChanged('name')}/>
<input type="password" placeholder="Enter password" onChange={this.props.dataChanged('password')}/>
</div>
);
}
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
handleChange = form => field => ev => {
this.setState(prev => ({ [form]: { ...prev[form], [field]: ev.target.value } }))
}
The resulting state of your parent will have the following structure :
{
'firstForm': {
'name': '',
'password': ''
},
'secondForm': {
'name': '',
'password': ''
}
}

Why data is not rendered on refresh in react js with asynchronous call?

I am creating edit form.First i have to get data to edit form and i am calling it in componentDidMount().Please see code below.
import React from 'react';
import CompanyForm from './CompanyForm';
import { connect } from 'react-redux';
import { companyActions } from '../../../redux/actions/company-action';
class EditCompanyPage extends React.Component {
constructor(props){
super(props);
};
componentDidMount () {
const { id } = this.props.match.params
const { dispatch } = this.props;
dispatch(companyActions.getCompany(id));
}
render(){
const {editUser } = this.props;
return(
<div>
<h1>Edit Company</h1>
{
editUser && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
}
</div>
);
};
}
function mapStateToProps(state) {
const { editUser } = state.companyReducer;
return {
editUser
};
}
const EditCompany = connect(mapStateToProps)(EditCompanyPage);
export default EditCompany;
see code for CompanyForm component below:
import React from 'react';
class CompanyForm extends React.Component {
constructor(props){
super(props);
this.state = {
company :{
name : this.props.companyDataFP.name || '',
address1 : this.props.companyDataFP.address1 || '',
}
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
handleChange(e) {
const { name, value } = e.target;
const newState = Object.assign({}, this.state);
newState.company[name] = value;
this.setState(newState);
}
handleSubmit(e) {
e.preventDefault();
return false;
}
render(){
return(
<div className="col-md-12">
<form onSubmit={this.handleSubmit}>
<div className="row">
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="name">Name</label>
<input type="text" name="name" className="form-control" onChange={this.handleChange} value={this.state.company.name} />
</div>
</div>
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="address1">Address 1</label>
<input type="text" name="address1" className="form-control" onChange={this.handleChange} value={this.state.company.address1} />
</div>
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className='form-group'>
<input type="submit" className="btn btn-info" value="submit" />
</div>
</div>
</div>
</form>
</div>
);
};
}
export default CompanyForm;
It works fine when i access this form with
<Link to="/edit-form/:id" >Edit</Link>
but when i refresh the current page then values are not rendering into form to edit.
I am using redux approach for state management, please guide me i am new to react.
Probably ComponyForm initializes form on its componentDidMount lifecycle function, so when editUser arrives nothing will change.
A way to handle this is changing:
<CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
to:
{editUser.name && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />}

React Redux setState after action is dispatched

This is my EditStudent component in React where I am using Redux for state management. This is my code of the component.
import React, { Component } from 'react'
import {connect} from 'react-redux';
import {getStudentDetail} from '../actions/studentActions';
class EditStudents extends Component {
constructor(props){
super(props);
this.onInputChange = this.onInputChange.bind(this);
this.state = {
name:this.props.student.name,
email:this.props.student.email,
address:this.props.student.address
}
// this.state
}
render() {
return (
<div>
<form>
<p>
<label>Name</label>
<input type="text" name="name"
value={this.state.name}
onChange={this.onInputChange}
/>
</p>
<p>
<label>Email</label>
<input type="text" name="email"
value={this.state.email}
onChange={this.onInputChange}
/>
</p>
<p>
<label>Address</label>
<input type="text" name="address"
value={this.state.address}
onChange={this.onInputChange}
/>
</p>
<button type="submit">Update</button>
</form>
</div>
)
}
onInputChange(e){
var name = e.target.name;
this.setState({[name]:e.target.value});
}
componentDidMount(){
this.props.getStudentDetail(this.props.studentId());
}
}
let mapDispatchToProps = (dispatch,ownProps)=>{
return {
getStudentDetail: (id)=>{
dispatch(getStudentDetail(id));
},
studentId: ()=>{
return ownProps.match.params.id;
}
}
}
const mapStateToProps = (state)=> {
return {
student:state.students.student
}
}
export default connect(mapStateToProps,mapDispatchToProps)(EditStudents);
Here I am having the problem displaying ajax response in text input field. I am setting component in the constructor but when ajax request completes state is not set.
Is it possible to set state after ajax completes?
I solve it by adding componentWillReceiveProps() function on component.
componentWillReceiveProps(nextProps){
this.setState({
name:nextProps.student.name,
email:nextProps.student.email,
address:nextProps.student.address
})
}
Thanks so much, Sakhi Mansoor for the help.
you need to store input value in your state as you're re-rendering your input so changes are not getting reflected.
Do the folowing changes:
constructor(props){
super(props);
this.onInputChange = this.onInputChange.bind(this);
this.state = {
email:this.props.student.email,
address: this.props.student.address
}
}
In you render:
<p>
<label>Email</label>
<input type="text" name="email" value={this.state.email} onChange={this.onInputChange('name)}/>
</p>
<p>
<label>Address</label>
<input type="text" name="address" value={this.state.address} onChange={this.onInputChange('name')}/>
</p>
onInputChange= name => event => {
this.setState({
[name]: event.target.value,
});
};
There are two ways
First -
constructor(props) {
super(props);
this.state = {
firstName: ""
};
}
componentDidMount() {
this.props.userProfile(); // Redux Action
}
componentWillReceiveProps(nextProps) {
console.log(nextProps);
this.setState({
firstName: nextProps.user.firstName
});
}
Second -
constructor(props) {
super(props);
this.props.userProfile(); // Redux Action
this.state = {
firstName: ""
};
}
static getDerivedStateFromProps(props, state) {
return {firstName: this.props.user.firstName };
}

reset button clears the input but deosn't re-render the component, how it works then?

I am using React. In the code below, when I click on the Reset button, it clears the input and set the default value 'Dear .' back.
What is happening? why doesn't it reset the Dear . too? and after clicking on Reset button I assume that it re-renders, but console.log('rende'); is not called! why?
import React from 'react';
import { connect } from 'react-redux';
class SearchBar extends React.Component {
constructor(props) {
super(props);
console.log('cons');
this.onInputchange = this.onInputchange.bind(this);
this.state = { name: 'Dear. ' };
}
onInputchange(event) {
console.log(event.target.value);
this.setState({ name: event.target.value });
}
render() {
console.log('rende');
return (
<form className="input-group">
<input
className="form-control"
value={this.state.name}
onChange={this.onInputchange}
placeholder="enter the name please "
/>
<span className="input-group-btn">
<button type="reset" className="btn btn-secondary">Reset</button>
</span>
</form>
);
}
}
export default connect()(SearchBar);
your code should be like this. You're directly change DOM element without reactjs lifecycle & Virtual DOM concepts.
import { connect } from 'react-redux';
class SearchBar extends React.Component {
constructor(props) {
super(props);
console.log('cons');
this.onInputchange = this.onInputchange.bind(this);
this.onResetHandler = this.onResetHandler.bind(this);
this.state = { name: 'Dear. ' };
}
onInputchange(event) {
console.log(event.target.value);
this.setState({ name: event.target.value });
}
onResetHandler(e) {
e.preventDefault();
this.setState({ name: 'Dear. '});
}
render() {
console.log('rende');
return (
<form className="input-group">
<input
className="form-control"
value={this.state.name}
onChange={this.onInputchange}
placeholder="enter the name please "
/>
<span className="input-group-btn">
<button type="button" className="btn btn-secondary" onClick={this.onResetHandler}>Reset</button>
</span>
</form>
);
}
}
export default connect()(SearchBar);
You need to prevent the default event for the button, if it's inside a form.
In React, it's often to use div rather than form tag, since the default behavior for form is to jump to next page.
I'm using arrow function to simplify your code.
import React from 'react';
class SearchBar extends React.Component {
state = { name: 'Dear. ' };
onInputchange = event => {
this.setState({ name: event.target.value });
}
onResetClick = event => {
event.preventDefault();
this.setState({ name: 'Dear. ' });
}
render() {
return (
<form className="input-group">
<input
className="form-control"
value={this.state.name}
onChange={this.onInputchange}
placeholder="enter the name please "
/>
<span className="input-group-btn">
<button className="btn btn-secondary" onClick={this.onResetClick}>Reset</button>
</span>
</form>
);
}
}
export default SearchBar;
The behavior of type='reset' is not to clear the form elements, but to return them to the initial/default values when the page was loaded.
The reset button resets the form's inputs to their initial values, not
to blank. The reset button is used to clear all inputs by the user.
You have loaded input with value={this.state.name} so it have it's own value on load by default. So whenever you click reset, it's return to default value you passed. To actually clear the form, you will need to use Events.
For your understanding clear your value={this.state.name} to defaultValue=""
Now try to type in your input then click reset !!! you got it.
check this example
read this doc

Resources