简体   繁体   中英

onClick event handler not firing when updating state directly - ReactJS

I'm new to ReactJS. I have the following code, in which I try to update UI by updating state using an onClick event handler. However, the onClick is not firing and it's not even showing on the final HTML. I can see the button but the button is not bound to the event handler. My code is:

import React from 'react';

class App extends React.Component {
   constructor() {
      super();
      this.state = {
         data: []
      }
      this.setStateHandler = this.setStateHandler.bind(this);
   }
   setStateHandler() {
      var item = "setState...";
      var myArray = this.state.data;
      myArray.push(item)
      this.setState({data: myArray})
   }
   render() {
      return (
         <div>
            <button onClick = {this.setStateHandler}>SET STATE</button>
            <h4>State Array: {this.state.data}</h4>
         </div>
      );
   }
}

export default App;

My final HTML rendered on the browser is:

<html lang="en"><head>
      <meta charset="UTF-8">
      <title>React App</title>
   <style type="text/css"></style></head>

   <body>
      <div id="app">
        <div>
          <button>SET STATE</button><h4>State Array: </h4>
        </div>
      </div>
 <script src="index.js"></script>
</body>
</html>

What am I doing wrong?

EDIT:

When I change var myArray = this.state.data; to var myArray = this.state.data.slice(); it works as intended.

You shouldn't see onClick handler in your HTML, that's how React works.

Working code:

class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         data: []
      }
      this.setStateHandler = this.setStateHandler.bind(this);
   }

   setStateHandler() {
      var item = "setState...";
      this.setState(prevState => ({ data: [...prevState.data, item]}));
   }

   render() {
      return (
         <div>
            <button onClick = {this.setStateHandler}>SET STATE</button>
            <h4>State Array: {this.state.data}</h4>
         </div>
      );
   }
}

export default App

The problem in your example is within setStateHandler definition. You are modifying state directly which is not a correct way to update state .

   setStateHandler() {
      var item = "setState...";
      this.setState(prevState => ({ data: [...prevState.data, item]}));
   }

In my example I use function as an argument to setState ( read when to use function as argument ) which will pass me a copy of component state. Then I use destructuring assignment (...prevState) to create new array with a item element. At last I return object to be merged into state.

Note that I used destructuring assignment for convenience and brevity. You can accomplish the same by just cloning the array:

   setStateHandler() {
      var item = "setState...";
      this.setState(prevState => {
        const newArray = prevState.data.slice();
        newArray.push(item);
        return { data: newArray };
      });
   }

Beside that you should also pass props to base constructor . But that wasn't the issue in this case.

尝试改用{String(this.state.data)}{this.state.data.toString()}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM