Search code examples
reactjsonchange

onChange not working in React for input box


I have a input box where I am showing the value if there is any fetched from the database and the input text box is editable. However, this input box doesn't reflect the changes on key press.

Here is the necessary following code:

constructor(props) {
    super(props)
    const { minorModel } = this.props;
    this.state =
    {
        galleryModel: minorModel.galleryModel,
        selectedIndex: 0           
    }
}
componentDidUpdate() {
    this.props.minorModel.galleryModel = this.state.galleryModel;
    
}

onInputChange=(e)=>{
   this.setState({
       [e.target.name]:e.target.value
   })
    
}
{this.state.galleryModel.photos.length > 0 && 
   <PtInput type="text" label="Comment" 
         value={this.state.galleryModel.Comments[this.state.selectedIndex] === null ? 
                  "Not Available " : 
             this.state.galleryModel.Comments[this.state.selectedIndex]}
               onChange={this.onInputChange} 
           name={`${"Comment "+[this.state.selectedIndex]}`} 
               disabled={this.props.disabled}
      />     
            }

I probably think the problem is because I am using a data model which is passed as props in the constructor and the values in that data model is not changing so the new value is not reflected. Is that so? Any help is really appreciated to solve this issue.I also have a componentDidUpdate to reflect the changes.


Solution

  • There is no connection between the value attribute and your onChange handler, since they aren't relying on the same state, thus you have an uncontrolled input.

    When the component mounts, you can load your data into the same state that is used to control the input.

    Here is a simplified potential implementation:

    class App extends React.Component {
      constructor() {
        super();
        this.state = {
          "pics": ['https://placehold.co/200x100',  'https://placehold.co/200x100'],
          "comments": [["comment 1 pic 1", "comment 2 pic 1"], ["comment 1 pic 2", "comment 2 pic 2"]],
        }
      }
      render() {
        return (
          <div>
            {this.state.pics.map((pic, i) => 
               <Picture pic={pic} comments={this.state.comments[i]} />)}
          </div>
        )
      }
    }
    
    const Picture = ({ pic, comments }) => {
      return <div>
        <img src={pic} />
        {comments.map(comment => <Comment comment={comment} />)}
      </div>
    }
    
    class Comment extends React.Component {
      constructor(props) {
        super(props);
        this.state = { value: this.props.comment };
        this.handleChange = this.handleChange.bind(this);
      }
    
      componentDidUpdate() {
        // do stuff when Comment component updates
      }
    
      handleChange(e) {
        this.setState({ value: e.target.value });
      }
    
      render() {
        return (
          <input 
            type="text" 
            value={this.state.value} 
            onChange={this.handleChange} 
          />
        );
      }
    }
    ReactDOM.render(<App />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    Also, you shouldn't be updating props inside a component. They are meant to be immutable and top-down.