ProEvilz
ProEvilz

Reputation: 5445

ReactJS: Why does my textarea value always render invisible?

Trying to set up something simple.

Parent: app.js

class App extends React.Component {
  constructor(props) {
    super(props);
    //This acts as our global state
    this.state = {
      username: "",
      email: "",
      bio: ""
    };
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({
        username: "jonny",
        email: "[email protected]",
        bio: "My bio...."
      });
    }, 5000);
  }
  handleFormChange = data => {
    this.setState(data);
  };
  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <Form data={this.state} onHandleFormChange={this.handleFormChange} />
        <p>Name from App state: {this.state.username}</p>
        <p>Email from App state: {this.state.email}</p>
        <p>Bio from App state: {this.state.bio}</p>
      </div>
    );
  }
}

Child: form.js

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      ...this.props.data
    };
  }
  handleSubmit = e => {
    e.preventDefault();
  };
  handleChange = e => {
    this.props.onHandleFormChange({ [e.target.name]: e.target.value });
  };
  // static getDerivedStateFromProps(nextProps, prevState) {
  //   console.log(nextProps.data)
  //   return {
  //     ...nextProps.data
  //   };
  // }
  componentDidUpdate(prevProps) {
    if (prevProps.data !== this.props.data) {
      this.setState({ ...this.props.data });
    }
  }
  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input
            type="text"
            name="username"
            defaultValue={this.state.username}
            onChange={this.handleChange}
          />
          <input
            type="email"
            name="email"
            defaultValue={this.state.email}
            onChange={this.handleChange}
          />
          <textarea
            name="bio"
            defaultValue={this.state.bio}
            onChange={this.handleChange}
          />
          <input type="submit" value="submit" />
        </form>
      </div>
    );
  }
}

I created an artificial API call by using a setTimeout() in this example and I'm trying to set the state of the parent with the result of the API call. Then I wish to pass that as a prop to the child...

It's working except in the case of a textarea. I can see it if I inspect the DOM but it doesn't actually show in the browser...

Note the "my bio..." in the inspector, but the textarea being empty in the browser.

enter image description here

I've tried componentWillUpdate(), componentDidUpdate() and getDerivedStateFromProps() but nothing seems to work.

What am I missing?

Note: I am not using value="" because then it stops me typing and this form is supposed to allow you to update existing values

Sandbox... https://codesandbox.io/s/ancient-cloud-b5qkp?fontsize=14

Upvotes: 0

Views: 377

Answers (2)

Koassi AKAKPO
Koassi AKAKPO

Reputation: 9

Change the defaultValue in textarea to value

Upvotes: 0

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15698

It seems to work fine by using the value attribute instead of defaultValue. The defaultValue attribute should really only be used sparingly, since you almost always want your inputs to connect to component state. The optimal way to create a controlled input is by using value.

      <textarea
        name="bio"
        value={this.state.bio}
        onChange={this.handleChange}
      />

Upvotes: 3

Related Questions