在反应生命周期内更新状态不起作用

时间:2019-10-10 07:52:23

标签: javascript reactjs

所以像这样的最初问题是,当onChange事件遇到API时,我有一个组件从语言组件中选择要导入到登录组件中的语言,然后将来自API的响应放入本地存储中。我从本地存储中检索要在登录组件中调用的数据,并进入登录组件状态,该数据未作为本地存储更新,但是如果成功更新了本地存储数据,如何在生命周期中更新状态? / p>

这是组件登录的状态

constructor(props){
    super(props)
    this.state = {
      getDataLocal:[]
    }
  }

我想从本地存储中获取数据并更新为状态

componentDidUpdate(){
    //set state and get data from localstorage
    this.setState({
      getDataLocal:JSON.parse(this.props.resGet('toLocalPages')),
      loading:false
    })
  }

更新失败,仍然包含一个空数组

render() {
    const { loading,getDataLocal} = this.state

    //getDataLocal unsuccessfully updated and still contains an empty array
    console.log(getDataLocal)

    if(this.state.redirect){
      return <Redirect to='/home' />
    }
    //untuk menghandle data di localstorage
    if(this.props.resGet('data')){
      return <Redirect to='/home' />
    }

    if(loading){
      return(
        <p>loading</p>
      )
    }else{
      return (
        <React.Fragment>
          <Container>
            <Padding />
              <Row>
                <Col md={{ span: 6, offset: 3 }} className='mx-auto'> 
                <Card>
                  <CardContent>
                    <Row>
                      <Col xs={12}>
                        <h3><b>{getDataLocal.page_login.title}</b></h3>
                        <p><b>{getDataLocal.page_login.subtitle}</b></p>
                        <br />
                      </Col>
                    </Row>
                    <Form onSubmit={this.handleSubmit}>
                      <SelectLanguage />
                      <Form.Group controlId='formBasicEmail'>
                        <Form.Label><b>{getDataLocal.page_login.label1}</b></Form.Label>
                        <Form.Control type='email' name='MEMBER_EMAIL' placeholder={getDataLocal.page_login.placeholder_label1} onChange={this.handleChange} />
                      </Form.Group>
                      <Form.Group controlId='formBasicPassword'>
                        <Form.Label><b>{getDataLocal.page_login.label2}</b></Form.Label>
                        <Form.Control type='password' name='MEMBER_PASSWORD' placeholder={getDataLocal.page_login.placeholder_label2} onChange={this.handleChange} />
                      </Form.Group>
                      <p className='text-muted float-right'><b>{getDataLocal.page_login.forgot_password}</b></p>
                        <Button type='submit' variant='warning' className='text-white' size='md' block >{getDataLocal.page_login.button}</Button>
                    </Form>
                    <br/>
                    <p className='text-muted text-center'><b>Or</b></p>
                    <p className='text-primary text-center'><b><i className='fa fa-facebook-official' aria-hidden='true'></i>&nbsp;{getDataLocal.page_login.link_login}</b></p>
                    <br />
                    <p className='text-muted text-center'><b>{getDataLocal.page_login.text2}&nbsp;<Link to='/register'><span className='text-warning'>{getDataLocal.page_login.link_register}</span></Link></b></p>
                  </CardContent>
                </Card>
              </Col>
            </Row>
          </Container>
        </React.Fragment>
      )
    }
  }
}

3 个答案:

答案 0 :(得分:0)

您可以在componentDidUpdate()中立即调用setState(),但请注意,必须将它包装在一个条件中。 注意- 如果componentDidUpdate()返回false,则不会调用shouldComponentUpdate()

答案 1 :(得分:0)

有两件事,首先,您不能直接调用componentDidUpdate,而必须检查组件的propsstate是否改变才能执行某些操作,其次,您尝试分配一个最初未定义的状态loading,您可以执行以下操作:

state = {
  getDataLocal: [],
  loading: false
}

componentDidUpdate(prevProps) {
  const { resGet } = this.props;

  if (prevProps.resGet('toLocalPages') !== resGet('toLocalPages')) {
    // Set state and get data from localstorage
    this.setState({
      getDataLocal: JSON.parse(resGet('toLocalPages')),
      loading: false
    })
  }
}

希望这会有所帮助。

答案 2 :(得分:0)

我想问题是改变道具不叫渲染。似乎getDerivedStateFromProps会对您有所帮助,因为它在之前的相同情况下对我有帮助。

  static getDerivedStateFromProps(props, state) {
    return{
      getDataLocal:JSON.parse(this.props.resGet('toLocalPages'))
    };
  }

只需尝试一下,让我知道它是否有效。