简体   繁体   English

React.js,为什么我的类组件不重新渲染元素,但是功能组件可以工作?

[英]React.js, why my class component doesn't rerender the element, but functional component can work?

I'm new to react.js, just follow the tutorial. 我是react.js的新手,只需按照教程进行即可。 Here is my code. 这是我的代码。 At first, i tried to use the class Component 'Greeting' to let it show different words after clicked the button, but i don't know what's wrong, it doesn't rerender the element, and the construtor() method of Greeting only called once. 最初,我尝试使用Component'Greeting'类让它在单击按钮后显示不同的单词,但我不知道出了什么问题,它没有重新呈现该元素,并且仅使用Greeting的construtor()方法打电话一次。 The commented out code functional Component 'Greeting' works well. 注释掉的代码功能组件“问候”效果很好。 Not sure what's the difference :( 不知道有什么区别:(

class GreetingGuest extends React.Component {
    render() {
        return (
            <h3>hello Guest, Click login button !!! </h3>
        );
    }
}

class GreetingUser extends React.Component {
    render() {
        return (
            <h3>You have logged in, welcome !!!</h3>
        );
    }
}

class Greeting extends React.Component {
  constructor(props) {
      super(props);   
      console.log('Greeting.state.is_logon = ', props.is_logon);
      this.state = {is_logon: props.is_logon};
  }

  render() {
      let welcome_msg = null;
      if (this.state.is_logon) {
          welcome_msg = <GreetingUser />;                 
      }else {
          welcome_msg = <GreetingGuest />;    
      }
      return welcome_msg; 
  }
}

//function Greeting(props) {
//    const is_logon = props.is_logon;
//    if (is_logon) {
//        return <GreetingUser />;
//    }
//    return <GreetingGuest />;
//}

class LoginComponent extends React.Component {
    constructor(props) {        
        super(props);           
        this.state = {is_logon: false};
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
        this.setState(prevState => ({
            is_logon: !prevState.is_logon
        }));
    }

    render() {
        let button = null;
        let greeting = null;

        if (this.state.is_logon) {
            button = (
                <button onClick={this.handleClick}>Logout</button>
            );

            greeting = <Greeting is_logon={this.state.is_logon} />
        }else {
            button = (
                <button onClick={this.handleClick}>Login</button>
            );
            greeting = <Greeting is_logon={this.state.is_logon} />
        }
        return (
            <div>
                {greeting}
                {button}
            </div>
        );
    }
}

ReactDOM.render(
    <LoginComponent />,
    document.getElementById('Login')
)

HTML: HTML:

<html>
<body>
     <div id="Login"></div>
</body>
<html>

The reason the class component doesn't re render, is because you have stored the logged_in prop in state from the constructor, and the constructor is only called once. 类组件不重新呈现的原因是因为您已从构造函数中存储了logged_in道具的状态,并且构造函数仅被调用一次。 Also state can only be modified from within the component. 而且状态只能在组件内部进行修改。

To fix this you have 2 options; 要解决此问题,您有2个选项;

Use componentWillReceiveProps , and update the local state with the new logged_in prop. 使用componentWillReceiveProps ,并使用新的logged_in道具更新本地状态。

componentWillReceiveProps(nextProps) {
  if (nextProps.logged_in !== this.state.logged_in) {
    this.setState({ logged_in: nextProps.logged_in });
  }
}

Or; 要么; do not use state but use the prop directly. 不要使用状态,而是直接使用道具。

  render() {
      let welcome_msg = null;
      if (this.props.is_logon) {
          welcome_msg = <GreetingUser />;                 
      }else {
          welcome_msg = <GreetingGuest />;    
      }
      return welcome_msg; 
  }

Where I think you should use the latter, since the parent component already maintains state. 我认为您应该使用后者,因为父组件已经维护了状态。

Well to be honest the answer which I posted previously was wrong. 老实说,我以前发布的答案是错误的。 It was because the way you posted the question telling that everything works fine when function based component is added. 这是因为您发布问题的方式是,添加基于功能的组件后一切正常。 Then I created a project using your code and figured out few issues in your code. 然后,我使用您的代码创建了一个项目,并找出了代码中的几个问题。

Firstly you are maintaining state locally outside redux here. 首先,您在此处在redux之外本地维护状态。 You are passing down the state of the login from the parent LoginComponent to the child component called Greeting like this. 您正在将登录状态从父LoginComponent到名为Greeting的子组件,如下所示。

greeting = <Greeting is_logon={this.state.is_logon} />

This gets passed as a props to the child component which is Greeting in this case. 这被作为道具的子组件被传递Greeting在这种情况下。 Remember React uses one way data flow . 请记住,React使用一种数据流方式

Now from that child component you can access the data using this.props as shown below. 现在,您可以从该子组件中使用this.props访问数据,如下所示。 You don't need to maintain any local state what so ever there. 您无需在那里维护任何本地状态。 Do the following changes in your Greeting component. 在“ Greeting组件中进行以下更改。

  constructor(props) {
      super(props);
  }

Then make sure you access the values from this.props instead of any local state object like this. 然后确保您从this.props中访问值,而不是像这样的任何本地状态对象。

 render() {
      let welcome_msg = null;
      if (this.props.is_logon) {
          welcome_msg = <GreetingUser />;
      }else {
          welcome_msg = <GreetingGuest />;
      }
      return welcome_msg;
  }
}

This solved the issue. 这解决了问题。 Happy Coding ! 编码愉快!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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