Search code examples
javascripthtmlreactjsreact-hooksantd

how to set the value of Input from state ( React app)


I am looking to set the value of Input from the state that I receive from props! I could set all the information from "profile" state in the placeholder but when putting it in the value field it doesn't show anything. Here's my code and the form I use :

<Form
    name="basic"
    wrapperCol={{ span: 24 }}
    onFinish={onUpdate}
    onFinishFailed={onFinishFailed}>
    <FormItem>
        <Input prefix={<ContactsTwoTone />} placeholder={profile.name} />
    </FormItem>

    <FormItem name="email"
        rules={[
            {
                type: 'email',
                message: 'The input is not valid E-mail!',
            }
        ]}
    >
        <Input value={profile.email} name="name" prefix={<MailTwoTone />} placeholder={profile}  />
    </FormItem>
    <FormItem name="mobile" value={profile.mobile} >
        <Input value={profile.mobile} name="mobile" prefix={<PhoneTwoTone />} placeholder={profile.mobile} />
    </FormItem>
    <FormItem name="addres">
        <Input name="addres" prefix={<HomeTwoTone />} placeholder={profile.addres} />
    </FormItem>
    <FormItem name="description">
        <Input.TextArea name="description" placeholder="description" rows={4} prefix={<ContainerTwoTone />} />
    </FormItem>
    <FormItem>
        <Button className="width-100" type="primary" htmlType="submit" onClick={onUpdate} >Update</Button>
    </FormItem>
</Form> 

The useEffect function and the declaration of state:

const [visible, setVisible] = useState(false);
const FormItem = Form.Item;
const [profile, setProfile] = useState({});

useEffect(() => {
    setProfile(props.profile); 
}, [props.profile]);

const showDrawer = () => {
    setVisible(true);
}; 

Solution

  • I am looking to set the value of Input from the state that i receive from props!

    If you're just looking to set the input from state, here is a simple example of that.

    Solution and Demo

    https://codesandbox.io/p/devbox/1q0ftq

    import { useState } from "react";
    
    const initialValue = "John";
    
    const App = () => {
      const [name, setName] = useState(initialValue);
    
      console.log("state: ", name);
    
      const handleChange = (event) => {
        const value = event.target.value;
        setName(value);
      };
    
      return (
        <div>
          <h2>Form</h2>
          <pre>Type in the input...</pre>
          <form>
            <input type="text" onChange={handleChange} value={name} />
          </form>
          <pre>state: {name}</pre>
        </div>
      );
    };
    
    export default App;
    

    Regarding the rest of your question and the example code, it looks like you may be thinking that props should inform some new state based on your useEffect.

    There are a couple issues here. You included a prop as a dependency in your useEffect. This is redundant because when props change, React already triggers a re-render. So, useEffect isn't necessary or applicable here. The new value will be available via props already. We can simply use it in our component, knowing that props are up-to-date. This makes the problem much more straightforward.

    You seem to essentially be asking about how to pass props into your form. Below is an example with editable profile section that is used to manage the profile state. The form section simply reads the values from state and displays the profile information. This illustrates the desired behavior you're describing. The form is just a component that receives the profile state passed down as props.

    The profile fields rely on state for their values. The form component relies on props based on that state.

    Example Passing Props to Component

    https://codesandbox.io/p/devbox/dawn-cloud-sbxmoz

    import { useState } from "react";
    
    const initialProfile = {
      firstName: "John",
      lastName: "Doe"
    };
    
    const Form = ({ firstName, lastName }) => (
      <div>
        <h2>Form</h2>
        <pre>Values based on profile...</pre>
        <form>
          <input
            label="First Name"
            type="text"
            name="firstName"
            value={firstName}
          />
          <input label="Last Name" type="text" name="lastName" value={lastName} />
        </form>
      </div>
    );
    
    const App = () => {
      const [profileFields, setProfileFields] = useState(initialProfile);
    
      const { firstName, lastName } = profileFields;
    
      console.log("profile fields: ", profileFields);
    
      const handleChange = (event) => {
        const { name, value } = event.target;
        setProfileFields(() => {
          return {
            ...profileFields,
            [name]: value
          };
        });
      };
    
      return (
        <div>
          <Form firstName={firstName} lastName={lastName} />
          <h2>Profile</h2>
          <pre>Type to edit profile fields...</pre>
          <form>
            <input
              label="First Name"
              type="text"
              onChange={handleChange}
              name="firstName"
              value={firstName}
            />
            <input
              label="Last Name"
              type="text"
              onChange={handleChange}
              name="lastName"
              value={lastName}
            />
          </form>
        </div>
      );
    };
    
    export default App;
    

    Explanation and Resources

    In the example, you can type in the profile fields to see how the form values are updated via props. Typing in the top form won't update values because these are read-only and "set from props".

    You might not want a read-only form, but this is just based on your example. You can pass your profile data as props to whatever component needs it.

    I think the idea I'm hoping to communicate here is to think about a "single source of truth" for your profile data (your state) and decide where you want that to live depending on what other components need to use it.

    This is commonly referred to as controlled versus uncontrolled components. The concept comes up often with form inputs since controlling the form with React state is very useful for accessing and validating inputs as a user types, which isn't easily achievable using HTML inputs in the traditional way.

    Resources

    https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components

    Hopefully that helps.