skip to Main Content

I’m trying to create components a (parent, child and input) and pass variables from the parent component to child and input components, allow for the variables to change within the child components and access the mutated variable in the parent component. With the below code, the text doesn’t update when typing in the input field, and my setValue function isn’t called in the parent component. Also, as you can see in my code below, the function setValue is there to handle all of the possible variable changes, but I’m not sure how to implement that. Any help would be greatly appreciated. Thank you.

const { useState } = React;

function CreateAccount() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');

  const setValue = (newValue, valueType) => {
    if (valueType === 'email') setEmail(newValue);
    else if (valueType === 'password') setPassword(newValue);
    else setConfirmPassword(newValue);
  };

  return (
    <div>
      <Form
        email={email}
        password={password}
        confirmPassword={confirmPassword}
        viewType='createClientAccount'
        onChangeState={setValue}
      />
      <hr/>
      <div>Email is:{email}</div>
    </div>
  );
}

function Form({ email, password, confirmPassword, viewType, onChangeState }) {
  if (viewType === 'createClientAccount') {
    return (
      <div className='box-shadow'>
        <h2>Create Client Account</h2>

        <TextInputField
          label={'Email'}
          value={email}
          onChangeState={onChangeState}
        />
      </div>
    );
  }
}

function TextInputField({ label, value, onChangeState }) {
  function onChange() {
    onChangeState(value);
  }

  return (
    <div className='inputFieldWrapper'>
      <p>{label}</p>
      <input name='email' value={value} onChange={onChange} />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<CreateAccount />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

2

Answers


  1. Your function onChange() in the TextInputField is not passing the change value to onChangeState(). It is only passing the value of the value prop, which is the original value being passed in from the parent.

    Additionally, the "onChange handler" for the <input> onChange prop is passed an Event object, from which you would extract the newly typed value.

    So try changing it to:

    function onChange(event) {
      const newValue = event.target.value;
    
      onChangeState(newValue)
    }
    
    Login or Signup to reply.
  2. There are several issues with the code you provided:

    1. your function onChange() in the TextInputField is not passing the change value to onChangeState(). It is only passing the value of the value prop, which is the original value being passed in from the parent.

    2. the "onChange handler" for the <input> onChange prop is passed an Event object, from which you would extract the newly typed value.

    3. the setValue() function you are passing down requires 2 parameters (type and value).

    4. the label props (which appears to be a rename of type expected by setValue() was given the value of "Email" but the code in setValue() was checking for the value of "email" (lower-case).

    This snippet I think shows a bit of what you were trying to accomplish?

    const { useState } = React;
    
    function CreateAccount() {
      const [email, setEmail] = useState('');
      const [password, setPassword] = useState('');
      const [confirmPassword, setConfirmPassword] = useState('');
    
      const setValue = (newValue, valueType) => {
        if (valueType === 'email') setEmail(newValue);
        else if (valueType === 'password') setPassword(newValue);
        else setConfirmPassword(newValue);
      };
    
      return (
        <div>
          <Form
            email={email}
            password={password}
            confirmPassword={confirmPassword}
            viewType='createClientAccount'
            onChangeState={setValue}
          />
          <hr/>
          <div>Email is: <span style={{color: 'red'}}>{email}</span></div>
        </div>
      );
    }
    
    function Form({ email, password, confirmPassword, viewType, onChangeState }) {
      if (viewType === 'createClientAccount') {
        return (
          <div className='box-shadow'>
            <h2>Create Client Account</h2>
    
            <TextInputField
              label={'email'}
              value={email}
              onChangeState={onChangeState}
            />
          </div>
        );
      }
    }
    
    function TextInputField({ label, value, onChangeState }) {
      function onChange(event) {
        const newValue = event.target.value;
        onChangeState(newValue, label);
      }
    
      return (
        <div className='inputFieldWrapper'>
          <p>{label}</p>
          <input name={label} value={value} onChange={onChange} />
        </div>
      );
    }
    
    ReactDOM.createRoot(document.getElementById('root')).render(<CreateAccount />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search