ReactJS:为什么在setState更改状态时调用构造函数

时间:2018-01-07 19:12:42

标签: javascript reactjs

我是 ReactJS 的新手,我已经创建了一个应用程序,您可以在其中提交姓名和电子邮件。名称和邮件应显示在页面底部的列表中。它显示的时间很短,但随后调用构造函数并清除状态和列表。

为什么在状态改变后调用构造函数?我认为构造函数只运行一次,然后render - 方法在setState()更改状态后运行。

class App extends React.Component {
    constructor(props) {
        super(props);

        console.log("App constructor");

        this.state = {
          signedUpPeople: []
        };

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

    signUp(person) {
        this.setState({
          signedUpPeople: this.state.signedUpPeople.concat(person)
        });
    }

    render() {
        return (
          <div>
            <SignUpForm signUp={this.signUp} />
            <SignedUpList list={this.state.signedUpPeople} />
          </div>
        );
    }
}

class SignUpForm extends React.Component {
    constructor(props) {
        super(props);

        console.log("SignUpForm constructor");

        this.state = {
          name: "",
          email: ""
        };

        this.changeValue = this.changeValue.bind(this);
        this.onSubmitForm = this.onSubmitForm.bind(this);
    }

    changeValue(event) {
        const value = event.target.value;
        const name = event.target.name;

        this.setState({
          name: value
        });
    }

    onSubmitForm() {
        this.props.signUp(this.state);
        this.setState({
          name: "",
          email: ""
        });
    }

    render() {
        console.log("SignUpForm render");
        return (
          <div>
            <h2>Sign up</h2>
            <form onSubmit={this.onSubmitForm}>
              <label htmlFor="name">Name:</label>
              <input id="name" name="name" onChange={this.changeValue} />
              <br />
              <label htmlFor="email">E-mail:</label>
              <input id="email" name="name" onChange={this.changeValue} />
              <input type="submit" value="Sign up" />
            </form>
          </div>
        );
    }
}

class SignedUpList extends React.Component {
    render() {
        console.log("SignedUpList render");
        return (
          <div>
            <h2>Already signed up</h2>
            <ul>
              {this.props.list.map(({ name, email }, index) => (
                <li key={index}>
                  {name}, {email}
                </li>
              ))}
            </ul>
          </div>
        );
    }
}

ReactDOM.render(<App />, window.document.getElementById("app"));

See CodePen example

3 个答案:

答案 0 :(得分:4)

form类型提交is to post back to the server input的默认行为。

  

<input>类型的元素&#34;提交&#34;被渲染为按钮。当。。。的时候   发生单击事件(通常是因为用户单击了按钮),   用户代理尝试将表单提交给服务器。

您可以传递提交处理程序的event对象,并使用event.preventDefault方法阻止表单发回:

onSubmitForm(e) {
      e.preventDefault();
      this.props.signUp(this.state);
      this.setState({
        name: "",
        email: ""
      });
    }

以下是代码的运行摘录:

&#13;
&#13;
class App extends React.Component {
    constructor(props) {
      super(props);
  
      console.log("App constructor");
  
      this.state = {
        signedUpPeople: []
      };
  
      this.signUp = this.signUp.bind(this);
    }
  
    signUp(person) {
      this.setState({
        signedUpPeople: this.state.signedUpPeople.concat(person)
      });
    }
  
    render() {
      return (
        <div>
          <SignUpForm signUp={this.signUp} />
          <SignedUpList list={this.state.signedUpPeople} />
        </div>
      );
    }
  }
  
  class SignUpForm extends React.Component {
    constructor(props) {
      super(props);
  
      console.log("SignUpForm constructor");
  
      this.state = {
        name: "",
        email: ""
      };
  
      this.changeValue = this.changeValue.bind(this);
      this.onSubmitForm = this.onSubmitForm.bind(this);
    }
  
    changeValue(event) {
      const value = event.target.value;
      const name = event.target.name;
  
      this.setState({
        name: value
      });
    }
  
    onSubmitForm(e) {
      e.preventDefault();
      this.props.signUp(this.state);
      this.setState({
        name: "",
        email: ""
      });
    }
  
    render() {
      //console.log('SignUpForm render');
      return (
        <div>
          <h2>Sign up</h2>
          <form onSubmit={this.onSubmitForm}>
            <label htmlFor="name">Name:</label>
            <input id="name" name="name" onChange={this.changeValue} />
            <br />
            <label htmlFor="email">E-mail:</label>
            <input id="email" name="name" onChange={this.changeValue} />
            <input type="submit" value="Sign up" />
          </form>
        </div>
      );
    }
  }
  
  class SignedUpList extends React.Component {
    render() {
      //console.log('SignedUpList render');
      return (
        <div>
          <h2>Already signed up</h2>
          <ul>
            {this.props.list.map(({ name, email }, index) => (
              <li key={index}>
                {name}, {email}
              </li>
            ))}
          </ul>
        </div>
      );
    }
  }
  
  ReactDOM.render(<App />, window.document.getElementById("app"));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app">

</div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

onSubmitForm(e) {
    e.preventDefault(); // prevent the form from refreshing the page 

    this.props.signUp(this.state);
    this.setState({
      name: "",
      email: ""
    });
}

它正在使用您的codepen链接:)

深入了解一下:

  

React - Preventing Form Submission

  

https://medium.com/@ericclemmons/react-event-preventdefault-78c28c950e46

答案 2 :(得分:0)

谢谢大家的帮助! : - )

  function setupMarker(idx, addresses, map, oms) {
    setTimeout(function() {
      var key = Object.keys(addresses['ASRAddr'])[idx];
      var state = addresses['ASRAddr'][key]['state']
      var position = new google.maps.LatLng(addresses['ASRAddr'][key]['latitude'], addresses['ASRAddr'][key]['longitude']);
      var zColors = {"green" : 1, "yellow" : 2, "red" : 3};
      var iw = new InfoBubble();

      marker = new google.maps.Marker({
        position: position,
        map: map,
        title: key + '\n' + addresses['ASRAddr'][key]['phyAddr'] + '\n\n' + getHC(key),
        zIndex: zColors[state],
        animation: google.maps.Animation.DROP,
        icon: "/static/images/googleMaps/" + state + "_MarkerA.png"
      });

      google.maps.event.addListener(marker, 'spider_click', function(e) {  // 'spider_click', not plain 'click'
        marker.addListener('mouseover', () => iw.open(map, marker));
        marker.addListener('mouseout', () => iw.close());
      });

      oms.addMarker(marker);  // adds the marker to the spiderfier _and_ the map
    }, 50*idx);
  }

  function initMap(addresses, map) {
     var oms = new OverlappingMarkerSpiderfier(map, {
       markersWontMove: true,
       markersWontHide: true,
       basicFormatEvents: true
     });

     for (i = 0; i < Object.keys(addresses['ASRAddr']).length; i++) {
      setupMarker(i, addresses, map, oms);
     }
  }

  function initPage() {
     var map = new google.maps.Map(document.getElementById('map'), {
       zoom: 5,
       center: new google.maps.LatLng(38.0000, -97.0000)
     });

     google.maps.event.addListenerOnce(map, 'idle', function(){
       decodeAddr(initMap, map);
     });
  }

修复了问题。谢谢!