12

If I want to make a functional component that will contain a form ,to login for example, and I want to contain the state in App component and Login will be its child, can I mutate the state in App using the form in Login child?

Alexander
  • 1,288
  • 5
  • 19
  • 38

6 Answers6

12
import React, {useState} from 'react';

function Submit() {

    const [inputField , setInputField] = useState({
        first_name: '',
        last_name: '',
        gmail: ''
    })

    const inputsHandler = (e) =>{
        setInputField( {[e.target.name]: e.target.value} )
    }

    const submitButton = () =>{
        alert(inputField.first_name)
    }

    return (
        <div>
            <input 
            type="text" 
            name="first_name" 
            onChange={inputsHandler} 
            placeholder="First Name" 
            value={inputField.first_name}/>

            <br/>

            <input 
            type="text" 
            name="last_name" 
            onChange={inputsHandler} 
            placeholder="First Name" 
            value={inputField.last_name}/>

            <br/>

            <input 
            type="gmail" 
            name="gmail" 
            onChange={inputsHandler} 
            placeholder="Gmail" 
            value={inputField.gmail}/>

            <br/>

            <button onClick={submitButton}>Submit Now</button>
        </div>
    )
}

export default Submit
Mehedi Setu
  • 119
  • 1
  • 3
  • 2
    This was great, except it causes a warning `Warning: A component is changing a controlled input of type text to be uncontrolled`. Fix for me for this here: https://stackoverflow.com/questions/61378837/react-input-warning-a-component-is-changing-a-controlled-input-of-type-text-to – tehlivi Oct 14 '21 at 15:36
5

Yes. Pass two props an object data and a method onChange to Login from App. data will set the values for the form in Login.

Fire onChange with updated form values if there is any change in Login form.

Handle it in App and update its state which will then flow down to Login as data.

Easwar
  • 5,132
  • 1
  • 11
  • 21
4

Use something like

const payloadHandler = (e) => {
    setPayload({ ...inputField, [e.target.name]: e.target.value });
};
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 4
    this is just a thrown snippet code without providing any further insights to the original question. – buzatto Feb 28 '21 at 02:51
3

Yes, this is possible. You just need to pass a prop to your child component. Here is an example of how to do it:

// in parent component

handleChange(updatedData) {
  this.setstate({
    data: updatedData
  })
}

// in render method
<Login handleChange={this.handleChange}/>

// in child component

// calling the handleChange function
this.props.handleChange(newData)
Arslan Tariq
  • 2,478
  • 2
  • 22
  • 45
1

The solution is given by the Mehedi Setu will give the Warning: A component is changing a controlled input of type text to be uncontrolled.

I am updating the code that will remove this Warning.

import React, {useState} from 'react';

function Submit() {

const [inputField , setInputField] = useState({
    first_name: '',
    last_name: '',
    gmail: ''
})

const inputsHandler = (e) =>{
    const { name, value } = e.target;
   setInputField((prevState) => ({
     ...prevState,
     [name]: value,
   }));
}

const submitButton = () =>{
    alert(inputField.first_name)
}

return (
    <div>
        <input 
        type="text" 
        name="first_name" 
        onChange={inputsHandler} 
        placeholder="First Name" 
        value={inputField.first_name}/>

        <br/>

        <input 
        type="text" 
        name="last_name" 
        onChange={inputsHandler} 
        placeholder="First Name" 
        value={inputField.last_name}/>

        <br/>

        <input 
        type="gmail" 
        name="gmail" 
        onChange={inputsHandler} 
        placeholder="Gmail" 
        value={inputField.gmail}/>

        <br/>

        <button onClick={submitButton}>Submit Now</button>
    </div>
)
}

export default Submit
Sachin Saini
  • 359
  • 2
  • 10
0

The set state process in React is an asynchronous process. Therefore even if the function is called, values has not updated the previous state just yet. To fix, this you can use the functional version of setState which returns the previous state as it's first argument.

Use this code below in order to get all the object values from the state

const inputsHandler = (e) => {
    setInputField((inputField) => ({
      ...inputField,
      [e.target.name]: e.target.value,
    }));
  };
Jamal Ashraf
  • 569
  • 6
  • 9