Search code examples
javascripthtmlreactjsonkeyup

onKeyUp not working in React where onChange did


I'm doing a React coding challenge that requires a value to be updated onKeyUp. I initially set it to update onChange but the tests require onKeyUp so I tried to change it to that, but my fields are no longer updating and I can't type anything into the textarea.

class MarkdownApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ''
    };

    this.handleKeyUp = this.handleKeyUp.bind(this);
  }

  handleKeyUp(event) {
    this.setState({ value: event.target.value })
  }

  render() {
    return (
      <form>
        <label>
          Enter your markdown here:
          <br />
          <textarea value={this.state.value} onKeyUp={this.handleKeyUp} id='editor' />
          <br />
        </label>
        <label>
          Your markup will be previewed here:
          <p id='preview'>{marked(this.state.value)}</p>
        </label>
      </form>
    );
  }
}

ReactDOM.render(
  <MarkdownApp />,
  document.getElementById('root')
);

Like I said, this worked fine when it was onChange and my function was handleChange, but since I switched it I can't type anything.


Solution

  • Since the event happens before the actual value of the textbox is changed, the result of event.target.value is an empty string. Setting the state with the empty string, clears the textbox.

    You need to get the pressed key value from the event, and add it to the existing state.value.

    Note: I've removed marked from the demo

    class MarkdownApp extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          value: ''
        };
    
        this.handleKeyUp = this.handleKeyUp.bind(this);
      }
    
      handleKeyUp(event) {
        const keyValue = event.key;
        
        this.setState(({ value }) => ({
          value: value + keyValue
        }))
      }
    
      render() {
        return (
          <form>
            <label>
              Enter your markdown here:
              <br />
              <textarea value={this.state.value} onKeyUp={this.handleKeyUp} id='editor' />
              <br />
            </label>
            <label>
              Your markup will be previewed here:
              <p id='preview'>{this.state.value}</p>
            </label>
          </form>
        );
      }
    }
    
    ReactDOM.render(
      <MarkdownApp />,
      document.getElementById('root')
    );
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    
    <div id="root"></div>