Changed value will also update the parent's state value

7 years ago
ReactJS
JavaScript

Continuing my experiment with React, I have made a few changes to the EditableText component. Primarily I would like to create a simple JSON editor, a react app that can create and update a JSON object. EditableText is to make editing the value of the JSON object kind of much easier. It is now updating the parent's state as well. The way I have made it is probably not perfect, but it is kind of working for now. Here is the updated EditableText component:

class EditableText extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      name: props.name,
      type: props.type||'text',
      value: props.value||'',
      editClassName: props.editClassName,
      edit: false,
      onChange:props.onChange
    }
  }
  edit() {
    this.setState({edit:edit!==false})
  }
  isChanged() {
    return this.state.backup!==this.state.value
  }
  hasChanged(event) {
    if (this.isChanged() && this.state.onChange)
      this.state.onChange(event)
  }
  render() {
    return (
      this.state.edit===true&&
      <input 
        name={this.state.name}
        type={this.state.type}
        value={this.state.value}
        className={this.state.editClassName}
        autoFocus
        onFocus={event=>{
          const value = event.target.value
          event.target.value = ''
          event.target.value = value
          this.setState({backup:this.state.value})
        }}
        onChange={event=>{
          this.setState({value:event.target.value})
        }}
        onBlur={event=>{
          this.setState({edit:false})
          this.hasChanged(event)
        }}
        onKeyUp={event=>{
          if(event.key==='Escape') {
            this.setState({edit:false, value:this.state.backup})
          }
          if(event.key==='Enter') {
            this.setState({edit:false})
            this.hasChanged(event)
          }
        }}
      />
      ||
      <span onClick={event=>{
          this.setState({edit:this.state.edit!==true})
        }}>
        {
          !this.state.value&&
          <span className="font-italic text-secondary">
            {'<empty>'}
          </span>
          ||
          this.state.value
        }
      </span>
    )
  }
}

What are the changes?

I pass an event handler function to the child component, the EditableText. On any changes to its value, the function will update the parent's state value as well.

<EditableText 
  value={this.state.value} 
  onChange={event=>{
    this.setState({value:event.target.value})
  }}
/>

I also made it displays <empty> in case the value is emptied. This is so that there is something to be clicked on when we want to update its value.

Here is a sample app made in codepen to demonstrate the way to utilize it, https://codepen.io/mjunaidi/pen/aLvGJb. The list can be added by clicking the Add button.

Thanks for reading!