I create a InputComponent and I want to import this component in other component and do submit, but I can't do it. how can I get value from child component in my FormComponent
InputComponent.js
import React, {Component} from 'react';
class InputComponent extends Component {
constructor(props) {
super(props);
this.state = { currentVal: null }
}
render() {
return (
<div>
<input
value={this.state.currentVal}
onChange={(event) => this.setState({currentVal:event.target.value })}
/>
</div>
);
}
}
export default InputComponent;
FormComponent.js
import React,{Component} from 'react';
import InputComponent from '../../components/common/InputComponent';
class FormComponent extends Component {
constructor(props) {
super(props);
this.state = { }
}
CallSubmit= (event) => {
// how can get username and password ?
event.preventDefault();
console.log(event.target.vale)
}
render() {
return (
<div style={{width:100, height:500, marginTop:100}}>
<form onSubmit={ this.CallSubmit }>
<InputComponent name="username" />
<InputComponent name="password" />
<button>Send it</button>
</form>
</div>
);
}
}
export default FormComponent;
You can create an onChange action on child component, for example here is your FormComponent:
Create this function to handle change:
onChangeUsername(username){
this.setState({username})
}
Passing the props to child component:
<InputComponent name="username" onChange = {this.onChangeUsername} />
And in the child component(InputComponent), you can access this props and pass the data to it:
this.props.onChange(event.target.value)
move your onChange functions in parent component and store username and password in FormComponent component
In React, data flows one way, from parent to children.
Therefore, you need to have the input' actual states at the FormComponent and pass them as props to the InputComponent, and the function that deals with it at the FormComponent either.
<div>
<InputComponent
input={this.state.username}
onChange={this.handleInputChange}
/>
<InputComponent
input={this.state.password}
onChange={this.handleInputChange}
/>
</div>
A good article to understand it: https://openclassrooms.com/en/courses/4286486-build-web-apps-with-reactjs/4286721-understand-one-way-data-bindings
Related
I wish to share this code just in case someone might need to solve such a problem of filtering unwanted characters when doing forms in react. For extras, my code shows how to pass props to components inside Route. For simplicity, I have focused on only these two inputs and omitted other stuff such as the submit button and css data for styling those classNames and ids.
import React, { Component } from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import SignupForm from "./components/SignupForm";
class App extends Component {
constructor() {
super();
this.state = {
firstName: "",
lastName: "",
};
//Binding this to the functions used as they wouldn't just work if not bound
this.changeFirstName = this.changeFirstName.bind(this);
this.changeLastName = this.changeLastName.bind(this);
this.lettersOnly = this.lettersOnly.bind(this);
}
changeFirstName(e) {
this.setState({ firstName: e.target.value });
}
changeLastName(e) {
this.setState({ lastName: e.target.value });
}
// Error handler functions
lettersOnly(nameInput) {//Replacing all characters except a-z by nothing with this function
let regex = /[^a-z]/gi;
nameInput.target.value = nameInput.target.value.replace(regex, "");
}
render() {
return (
<Router>
<div className="App">
<Route
exact
path="/"
comp={SignupForm}
render={() => (
<SignupForm
//SignupForm submit props
changeFirstNameHandler={this.changeFirstName}
firstNameValue={this.state.firstName}
changeLastNameHandler={this.changeLastName}
lastNameValue={this.state.lastName}
// Error handlers
nameCharacterFilter={this.lettersOnly}
/>
)}
/>
)}
/>
</div>
</Router>
);
}
}
export default App;
Below is the signup form, which is the child component in this aspect, and also a function component as opposed to its parent component:
import React from "react";
export default function SignupForm(props) {
return (
<div className="container" id="signupForm">
<h1>Signup Form</h1>
<div className="form-div">
<form>
<input
type="text"
placeholder="First Name"
onChange={props.changeFirstNameHandler}
value={props.firstNameValue}
onKeyUp={props.nameCharacterFilter}
className="form-control formgroup"
/>
<input
type="text"
placeholder="Last Name"
onChange={props.changeLastNameHandler}
value={props.lastNameValue}
onKeyUp={props.nameCharacterFilter}
className="form-control formgroup"
/>
</form>
</div>
</div>
);
}
NB: Welcome to improve this code, if you feel the need!
I think you can improve you're code with this changes:
Use the regex directly in the onChange event
Use only one method to update the values
Here is an example of what I mean: https://codesandbox.io/s/react-playground-forked-vreku?fontsize=14&hidenavigation=1&theme=dark
Regards!
Okay here is an improved code and much more cleaner. However, I have just omitted the React Router part to focus on functionality of the state and functions in this case.
I also want the user to see when they type an unwanted character that it actually typed but then just deleted on key up so I have created an independent function justLettersAndHyphen(nameField) from changeValue(event) that is triggered by onKeyUp.
import React from "react";
import SignupForm from "./SignupForm";
class App extends React.Component {
constructor() {
super();
this.state = {
firstName: "",
lastName: ""
};
this.changeValue = this.changeValue.bind(this);
this.justLettersAndHyphen = this.justLettersAndHyphen.bind(this);
}
changeValue(event) {
this.setState({
[event.target.name]: event.target.value,
});
}
// Error handler functions
justLettersAndHyphen(nameField) {
let regex = /[^a-z-]/gi;
nameField.target.value = nameField.target.value.replace(regex, "");
}
render() {
return (
<SignupForm
firstNameValue={this.state.firstName}
lastNameValue={this.state.lastName}
changeValueHandler={this.changeValue}
nameCharacterFilter={this.justLettersAndHyphen}
/>
);
}
}
export default App;
Child component edited with name property added.
import React from "react";
export default function SignupForm(props) {
return (
<div className="container" id="signupForm">
<h1>Signup Form</h1>
<div className="form-div">
<form>
<input
name="firstName"
type="text"
placeholder="First Name"
onChange={props.changeValueHandler}
onKeyUp={props.nameCharacterFilter}
value={props.firstNameValue}
/>
<input
name="lastName"
type="text"
placeholder="Last Name"
onChange={props.changeValueHandler}
onKeyUp={props.nameCharacterFilter}
value={props.lastNameValue}
/>
</form>
</div>
</div>
);
}
Any help or hint would be greatly appreciated.
In SearchBar.js, where is the "this.props" defined?
I don't see this variable being defined in the SearchBar.js class?
Is it because of React.Component class?
How can I go into this React.Component class when debugging in google chrome?
SearchBar.js:
import React from 'react';
class SearchBar extends React.Component {
state = { term: '' };
onFormSubmit = event => {
event.preventDefault();
this.props.onSubmit(this.state.term);
console.log(this.state.term);
}
render() {
return (
<div className="ui segment">
<form onSubmit={this.onFormSubmit} className="ui form">
<div className="field">
<label>Image Search</label>
<input type="text" value={this.state.term} onChange={(e) => this.setState({ term: e.target.value.toUpperCase()})} />
</div>
</form>
</div>);
}
}
App.js:
import React from 'react';
import SearchBar from './SearchBar';
class App extends React.Component {
onSearchSubmit(term) {
console.log(term);
}
render() {
return (
<div className="ui container" style={{ marginTop: '10px'}}>
<SearchBar onSubmit={this.onSearchSubmit} />
</div>
);
}
}
export default App;
export default SearchBar;
The superclass, React.Component, creates a props object on the instance and assigns to it any props passed to the instance. If you go to react.development.js (or to ReactBaseClasses.js), you'll see:
function Component(props, context, updater) {
this.props = props;
where the first argument, the props, will contain props the component was called with.
Here, since the component is invoked like this:
<SearchBar onSubmit={this.onSearchSubmit} />
It has one prop, onSubmit, so the props are:
{
onSubmit: this.onSearchSubmit
}
I have a simple code in [sandbox][1] and below
[1]: https://stackblitz.com/edit/react-72dprn to pass input form value to child to parent but something is wrong and the value didn't get passed.
This is the app.js
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import Form from './form'
class App extends Component {
constructor() {
super();
this.state = {
value: ""
};
}
handleSubmit = e=>{
this.setState({
value=e.target.value
})
}
render() {
return (
<div>
<Form onSubmit={this.handleSubmit}/>
</div>
);
}
}
render(<App />, document.getElementById('root'));
And the Form.js
import React, { Component } from 'react';
class form extends Component {
render() {
return (
<form className="replyForm" onSubmit={this.props.onSubmit}>
<input />
<button type="submit" className='btn btn-success'>Submit</button>
</form>); } }
export default form;
Any help greatly appreciated!
There are so many mistakes in your code. You should read the react docs properly
First of all you are setting your state incorrectly -
handleSubmit = e=>{
this.setState({
value: e.target.value //this is an object don't assign a value//
})
}
Second - In your form.js your component starts with a lowercase. React components start with an uppercase -
class Form extends Component {
render() {
return (
<form className="replyForm" onSubmit={this.props.onSubmit}>
<input />
<button type="submit" className='btn btn-success'>Submit</button>
</form>); } }
export default Form;
Now coming to your original question, To pass the value of input to child you need to pass it as props and use it in child as props -
<Form onSubmit={this.handleSubmit} inputValue={this.state.value} />
In your child component access that value as this.props.value.
I'm creating a ReactJS package. I've created a component called Form which contains a normal form. When calling it on the App.js I add components on it which called TextField. So, the code on App.js is:
import React, { Component } from 'react'
import { Form, TextField } from 'form2'
import './App.css'
export default class App extends Component {
render () {
return (
<div>
<Form>
<TextField placeholder="Type your name..." />
<TextField placeholder="Type your email..." />
</Form>
</div>
)
}
}
And the code of the Form component is:
import React, { Component } from 'react'
class Form extends Component {
constructor(props) {
super(props)
this.state = {
values: {}
}
}
renderChildren = () => {
return this.props.children;
};
render() {
return <form>
{ this.renderChildren() }
</form>
}
}
export default Form
And this is mt TextField component:
import React, { Component } from 'react'
class TextField extends Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}
onChange = ({ target }) => {
this.setState({ value: target.value });
};
render() {
return <input onChange={this.onChange} {...this.props}>
{this.state.value}
</input>
}
}
export default TextField;
The problem is happening when I type something on the input, the inputs disappeared and got this error message on the console:
The above error occurred in the <input> component
and this one
Uncaught Invariant Violation: input is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.
Change:
render() {
return <input onChange={this.onChange} {...this.props}>
{this.state.value}
</input>
}
To:
render() {
return <input defaultValue={this.state.value} onChange={this.onChange} {...this.props} />
}
Or (depending on the behavior your want):
render() {
return <input value={this.state.value} onChange={this.onChange} {...this.props} />
}
The existing code is trying to set the child of input to {this.state.value}.
import React from 'react';
import Child from './Child';
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {
firstName: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount(){
let fn = JSON.parse(localStorage.getItem("fir"));
if((localStorage.getItem("fir")!==undefined) && (localStorage.getItem("fir")!==null)){
this.setState({
firstName: fn
})
}
}
handleChange(e){
this.setState({
[e.target.name] :[e.target.value]
})
}
handleSubmit(){
localStorage.setItem("fir", JSON.stringify(this.state.firstName));
alert('submitted');
console.log(this.state.firstName)
}
render(){
return(
<div>
<p> Parent</p>
<Child
firstName={this.state.firstName}
handleChange={this.handleChange}
handleSubmit={this.handleSubmit}
/>
{this.state.firstName}
</div>
)
}
}
export default Parent;
2.
import React from "react";
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: props.firstName
};
}
render() {
return (
<div>
<p> Child</p>
<input
type="text"
name="firstName"
value={this.state.firstName}
onChange={this.props.handleChange}
/>
<button onClick={this.props.handleSubmit}> submit</button>
</div>
);
}
}
export default Child;
Here i want to update an input field in Child component, But i'm stucked. can anyone help to update that.
Change the below line in child
value={this.state.firstName}
to
value={this.props.firstName}
because firstname is being passed as a prop to child component
You need to pass the value you need to update has props then use that props in the value of your input in child component. I can see you already passing the firstName has a prop, you just to change state to props
<input
type="text"
name="firstName"
value={this.props.firstName}
onChange={this.props.handleChange}
/>