【问题标题】:React: Calling setState within render method throws errorReact:在渲染方法中调用 setState 会引发错误
【发布时间】:2018-10-23 14:53:04
【问题描述】:

正如标题所暗示的,只有在我的聊天窗口中收到第一条消息之后——这条初始消息是从 GET 请求中检索到的,所以它不是同步的——我想显示/呈现一个按钮。目前它抛出一个错误,说我无法在渲染方法中设置状态。

我还尝试了按钮类中的显示逻辑以及“父”类,这是我的消息列表,我将按钮放入其渲染方法中。

this.props.messages 是一个消息数组,'messages' 也是如此。 this.props.messages[0].data.text 是第一条消息,尽管当我尝试对其进行控制台时,它会在开发工具中对每条消息进行多次控制台,当然当我尝试显示按钮时它会引发 setState 错误.

我有一个简单的按钮类:

class Button extends Component {
render() {
    return (
        <div>
            {<button>Return</button >}
        </div>
    )
  }
}
export default Button;

还有我的 messageList 类,其中我有 this.props.messages 这是消息的数组, this.props.messages[0] 是第一条消息,如果我控制台,则 message..which 控制台的每条消息.记录一下。

如果我写任何一个(如果 message.data.text OR this.props.messages[0] === 'my first string'){ console.log ('.....'}那么它总是算作true 和 consoles 和 setstate 进入一个循环。

import Message from './Messages'
import Button from './Button'


class MessageList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showing: false,
    };
    this.showButton = this.showButton.bind(this);
  }

  showButton() {
    const { showing } = this.state;
    this.setState({
      // toggle value of `showing`
      showing: !showing,

    });
  }

  componentDidUpdate(prevProps, prevState) {
    this.scrollList.scrollTop = this.scrollList.scrollHeight;
  }

  onlyInitialMessage(message) {
    if (this.props.messages[0].data.text = `Hi I'm Joe your store assistant, I'm here to help. Here's what I can do: Answer questions on store policies, process a return or just general inquiries.`) {
      this.showButton();
    }
  }

  // way to render a function.
  // {this.renderIcon()}   


  render() {
    return (
      <div className="sc-message-list" ref={el => this.scrollList = el}>
        {this.props.messages.map((message, i) => {

          { this.onlyInitialMessage() }

          return <Message message={message} key={i} />
        })}

        {this.state.showing && <Button />}

      </div>)
  }
}

我不确定我的逻辑是不是放错地方了?我尝试移动它很多次,我是 React 新手!

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    首先,问题是您通过在渲染中调用{ this.onlyInitialMessage() } 间接设置渲染方法中的状态。

    其次,您的 if 条件不是比较值,而是分配始终返回 true 的值

    if (this.props.messages[0].data.text === `Hi I'm Joe your store assistant, I'm here to help. Here's what I can do: Answer questions on store policies, process a return or just general inquiries.`) {
    

    要解决它,你必须在 componentDidMount 中调用onlyInitialMessage

    import Message from './Messages'
    import Button from './Button'
    
    
    class MessageList extends Component {
      constructor(props) {
        super(props);
        this.state = {
          showing: false,
        };
        this.showButton = this.showButton.bind(this);
      }
      componentDidMount() {
          this.onlyInitialMessage();
      }
      showButton() {
        const { showing } = this.state;
        this.setState({
          // toggle value of `showing`
          showing: !showing,
    
        });
      }
    
      componentDidUpdate(prevProps, prevState) {
        this.scrollList.scrollTop = this.scrollList.scrollHeight;
      }
    
      onlyInitialMessage(message) {
        if (this.props.messages[0].data.text == `Hi I'm Joe your store assistant, I'm here to help. Here's what I can do: Answer questions on store policies, process a return or just general inquiries.`) {
          this.showButton();
        }
      }
    
      // way to render a function.
      // {this.renderIcon()}   
    
    
      render() {
        return (
          <div className="sc-message-list" ref={el => this.scrollList = el}>
            {this.props.messages.map((message, i) => {
    
              return <Message message={message} key={i} />
            })}
    
            {this.state.showing && <Button />}
    
          </div>)
      }
    }
    

    【讨论】:

    • 我应该提到,我的初始消息是从 GET 请求中检索到的,因此它与 componentDidMount 不同步 - 什么都没有出现!如果我将其注释掉,它就会回来。
    • 好的,那么你需要做的就是在检查props是否真的改变后,在componentDidUpdate中调用setState
    • 我得到 - '无法读取未定义的属性'数据''...这是一个聊天窗口,因此消息尚未存在,它们是通过请求返回的。
    • 哦,好吧,我试试看,我想我可以在网上找到有关如何做到这一点的资源?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2017-07-23
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    相关资源
    最近更新 更多