为什么在提交表单并使用Firebase设置状态后,我的组件没有重新呈现?

时间:2019-05-16 14:41:44

标签: javascript reactjs firebase google-cloud-firestore state

我正在构建一个应该在提交表单后重新呈现的组件,它可以很好地发送数据库,但是我希望该组件在提交后重新呈现,而不必刷新页面。

我听说状态更改后,React会重新渲染,并且尝试设置表单输入在提交时的状态。

import React, { Component } from 'react';
import { withFirebase } from '../Firebase';
import { FirebaseContext } from '../Firebase';
import { Link } from 'react-router-dom';
import AddNew from '../AddNew';
import { compose } from 'recompose';
import Firebase from '../Firebase';
import * as ROUTES from '../../constants/routes';
import { throwStatement, thisExpression, tsExpressionWithTypeArguments } from '@babel/types';



class Home extends Component {
  constructor(props) {
    super(props)
    this.state = {
      loading: false,
      isHidden: false,
      name: '',
      image: '',
      data: []
    }

    this.baseState = this.state

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

  getPosts() {
    this.props.firebase.getClients().then(snapshot => {
      this.setState({
        data: snapshot.docs
      })
    });
  }

  // Component lifecycle methods

  componentWillMount() {
    this.getPosts()
  }

  componentDidUpdate(){
    console.log('updated')
  }

  toggleAddNew() {
    this.setState({
      isHidden: !this.state.isHidden
    })
  }

  updateInput = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  resetForm = () => {
    this.setState(this.baseState)
  }

  deletePost = (id) => {
    this.props.firebase.deleteClient(id);
  }

  addClient = e => {
    e.preventDefault();

    this.props.firebase.addClient().add({
      name: this.state.name,
      image: this.state.image
    })
    this.setState({
      name: '',
      image: ''
    });
    this.resetForm();
  };


  render() {

    const renderPosts = this.state.data.map((item) => (

      <li data-id={item.id} className="client-wrapper col-sm-4">
        <button onClick={() => this.deletePost(item.id)}>X</button>
        <Link to={`/dates/${item.id}`}>
          <h2>{item.data().name}</h2>
        </Link>
        <Link to={`/dates/${item.id}`}>
          <img src={item.data().image} />
        </Link>
      </li>

    ));

    return (
      <div>
        <ul id="client-list" className="row">{renderPosts}</ul>
        <button onClick={this.toggleAddNew.bind(this)}>Add New</button>
        {this.state.isHidden ? 
        <div id="add-new-form-wrapper">
          <button onClick={this.toggleAddNew.bind(this)} id="x-add-new">X</button>
          <form onSubmit={this.addClient.bind(this)} id="add-new-form">
            <input type="text" name="name" placeholder="Name" onChange={this.updateInput} value={this.state.name} />
            <input type="text" name="image" placeholder="Image" onChange={this.updateInput} value={this.state.image} />
            <button type="submit">Submit</button>
          </form>
        </div> :
          ''}
      </div>
    )
  }

}

export default compose(
  withFirebase,
)(Home);

1 个答案:

答案 0 :(得分:0)

  

this.baseState = this.state

仅复制对象引用,而不复制状态对象(带有属性值)。

当我们有参考副本

  

resetForm = () => { this.setState(this.baseState) }

可以像state = state一样工作,什么也不做。

可以使用以下方式复制(带有当前属性值的)对象:

this.baseState = {...this.state}

有了这个小修正,它应该可以工作...

...如果没有,请尝试

resetForm = () => {
  this.setState({...this.baseState})
}

您还可以使用当前时间更新某些状态字段以强制重新渲染,或直接调用this.forceUpdate()(请参阅docs)。

顺便说一句-resetForm不应覆盖data。幸运的是,我们在data中有一个baseState对象引用的副本;)