In React how to PROPERLY pass input value from child to parent - reactjs

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.

Related

React input element's onChange using setState() doesn't work

I want to make an app so that when text is typed in input element this will reflect that change in output. So far the updating doesn't work :(
import React, { Component } from 'react';
import './App.css';
import UserInput from './UserInput/UserInput';
import UserOutput from './UserOutput/UserOutput';
class App extends Component {
state = {
user: [
{ username: 'Kai' },
{ username: 'Orange' }
]
}
inputChangeHandler = (e) => {
this.setState(
{
user: [
{ username: e.target.value },
{ username: e.target.value }
]
}
)
}
render() {
return (
<div className="App">
<UserInput onChange={this.inputChangeHandler} />
<UserOutput username={this.state.user[0].username} />
<UserOutput username={this.state.user[1].username} />
</div>
);
}
}
export default App;
Change in text typed in input element should be reflected as username rendered in UserOutput. This doesn't work.
Here are codes for other components...
import React, { Component } from 'react';
class UserInput extends Component
{
render() {
return(
<div>
<input />
</div>
);
}
}
export default UserInput;
and
import React, { Component } from 'react';
class UserOutput extends Component
{
render() {
return(
<div>
<p>First paragraph and my name is {this.props.username}</p>
<p>Second paragraph </p>
</div>
);
}
}
export default UserOutput;
Ok there's your problem. You're not assigning the change handler to the input element in your UserInput component. It should be:
<input onChange={this.props.onChange} />

How to create a to-do list in React without ref

I intend to create a to-do list without using ref as in the many examples, but it isn't working.
The expected behavior is that upon entering an entry, it will show up at the top and upon clicking add, it will create an input box for entering an entry. Currently, upon entering the state returns undefined.
The code can be found below or in this sandbox:
import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';
import ToDo from './todo'
class App extends Component {
constructor() {
super();
this.state = {
todos: []
};
}
onChange=(e)=>{
const newToDos = [...this.state.todos]
newToDos.push(e.target.value)
this.setState({
todos: newToDos
})
}
onAdd=(e)=>{
e.preventDefault();
const newtodos=[...this.state.todos]
this.setState({
todos: newtodos.push("")
})
}
render() {
console.log(this.state.todos)
return (
<div>
<p>All the to-dos include {this.state.todos}</p>
<ToDo
todos={this.state.todos}
/>
<form onSubmit={this.onChange}>
<input
type="text"
placeholder="add a new todo..."
/>
</form>
<button onClick={this.onAdd}>+</button>
</div>
);
}
}
render(<App />, document.getElementById('root'));
And here is the todo.js:
import React, { Component } from 'react';
import { render } from 'react-dom';
export default class ToDo extends Component {
constructor(props){
super(props)
}
render() {
const {todos, onChange}=this.props
return (
<div>
{
todos.map((todo, index)=>
<div>
{todo}
</div>
)
}
</div>
);
}
}
You can store your new todo in state when onChange input and add this into todos when click save.
I have forked and edit your sample.
https://stackblitz.com/edit/react-nwtp5g?file=index.js
BTW: In your sample, newtodos.push("") will return the length of newtodos array, not the array after pushed.
onAdd=(e)=>{
e.preventDefault();
const newtodos=[...this.state.todos]
this.setState({
todos: newtodos.push("")
})
Hope this help.
your code newtodos.push("") dosent return array so no map function:
this.setState({
todos: newtodos.push("")
})
correct it something like this
this.setState({
todos: newtodos.concat("new value")
})
You have a problem with this code,
<form onSubmit={this.onChange}>
<input
type="text"
placeholder="add a new todo..."
/>
</form>
Here you are adding onSubmit on form, which will never call because you don't have submit button.
you should do something like this,
<form>
<input
type="text"
placeholder="add a new todo..."
onChange={this.onChange}
value={this.state.currentValue}
/>
</form>
onChange=(e)=>{
event.preventDefault();
this.setState({
currentValue: e.target.value
})
}
onAdd=(e)=>{
e.preventDefault();
const newToDos = [...this.state.todos]
newToDos.push(this.state.currentValue)
this.setState({
todos: newToDos,
currentValue: ''
})
}
Demo
Update
In your todo component you have useless constructor, If you don't have state in a component or don't have any function to bind this don't add constructor.
You can remove the constructor.
Another thing is, you are not passing any onChange prop to todo component, so here you will get undefined for onChange.
const {todos, onChange}=this.props
You can also write this component as a functional component.
You can update your code with
import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';
import ToDo from './todo'
class App extends Component {
constructor() {
super();
this.state = {
todos: [],
inputText: ""
};
}
onAdd= () => {
this.setState({
todos: [...this.state.todos, this.state.inputText], textInput: ""
})
}
render() {
console.log(this.state.todos)
return (
<div>
<p>All the to-dos include {this.state.todos}</p>
<ToDo
todos={this.state.todos}
/>
<form>
<input
type="text"
placeholder="add a new todo..."
onChange={inputText => this.setState({inputText})}
/>
</form>
<button onClick={this.onAdd}>+</button>
</div>
);
}
}
render(<App />, document.getElementById('root'));
And in todo.js you can simply do
import React, { Component } from 'react';
import { render } from 'react-dom';
export default const ToDo = ({todos}) => {
return(<div>
{todos.map((todo, index) => (
<div key={index}>
{todo}
</div>))}
</div>)}
as it do not contains any state associated with it.

React render props.children fails when run children events (children are components)

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}.

How can get Value from child component in react?

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

can i pass a state value with the jsx code ?? in reactjs

Hello everybody I'm wondering if I can pass a state value from a component to other where I'm returning jsx code to be displayed for example I have 3 components.
1
import React, { Component } from 'react';
import Conteneur from './Conteneur';
class Header extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
<Conteneur values={this.state.value} />
</form>
);
}
}
export default Header;
2 app.js
import React, { Component } from 'react';
import Header from './Header';
import Conteneur from './Conteneur';
import './App.css';
class App extends Component {
render() {
return (
<div className="App" >
<br />
<Header />
<br />
<Conteneur />
</div>
);
}
}
export default App;
3 and finally
import React, { Component } from 'react';
const Conteneur = () => {
return (
<div className="tab"><span>ok test </span></div>
);
};
export default Conteneur;
I like to pass the state value of header that I have from the input to conteneur and then display in the box while I have some code all the examples that I saw online they are sending state like this:
class Dashboard extends Component {
...
...
render(){
return(
<Sidebar data={this.state.data1}/>
);
}
}
So can I do like this <Conteneur values={this.state.value} /> in the form ?
And I imported Conteneur.
i updated the code but the output is
Yes you can do, only one thing you are missing. Receive the props in the function parameters then render that in the ui.
Like this:
const Conteneur = (props) => {
return (
<div className="tab"><span>value: {props.value} </span></div>
);
};

Resources