Обновление локального состояния после рендеринга компонента - PullRequest
0 голосов
/ 14 июня 2019

Я создаю приложение для планирования проекта с использованием React, Redux и Firebase. Одна запись проекта в моей базе данных Firestore содержит Title и немного Content . Когда я иду обновить проект, у меня в полях ввода defaultValues ​​установлены правильные данные для проекта, который я хочу редактировать. Однако обновление работает только в том случае, если я внесу изменения в и поля ввода Содержимое и Название. В противном случае при отправке этих значений данные удаляются, так как в локальном состоянии не произошло каких-либо изменений, и поэтому обновляет нетронутое поле до пустой строки: ""

Я попытался установить локальное состояние компонента EditProject в методе рендеринга, но это невозможно:

render() {
    const { project, auth } = this.props;
    if (!auth.uid) return <Redirect to="/signin" />;
    if (project) {
      this.setState({
        title: project.title,
        content: project.content
      });

...

Я также пытался установить состояние во время componentDidMount, например, так:

  componentDidMount = () =>{
    const { project } = this.props;
    this.setState({
      title: project.title,
      content: project.content
    })
  }

Но проблема в том, что проектная опора не отображается на mapStateToProps до componentDidMount

Наконец, я попытался передать реквизиты проекта из родительского компонента, который является projectDetails, но я не могу успешно сделать это. Возможно, я неправильно выполняю эту часть, поэтому, пожалуйста, дайте мне знать, если есть хороший способ сделать это с помощью кода, который у меня есть. В ProjectDetails:

<Link to={"/edit/" + docId} key={docId}>
  <button className="btn pink lighten-1 z-depth-0">Edit</button>
</Link>

Это ссылка на «сломанный» компонент EditDetails, который я пытаюсь исправить.


Вот мой код для компонента EditProject

class EditProject extends Component {
  state = {
    title: "",
    content: ""
  };

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

  handleSubmit = e => {
    e.preventDefault();
    let localProject = this.state;
    let docId = this.props.docId;
    this.props.editProject(localProject, docId);
    const projectDetailURL = "/project/" + docId;
    this.props.history.push(projectDetailURL);
  };

  render() {
    const { project, auth } = this.props;
    if (!auth.uid) return <Redirect to="/signin" />;
    if (project) {
      return (
        <div className="container section project-details">
          <div className="card z-depth-0">
            <div className="card-content">
              <form onSubmit={this.handleSubmit} className="white">
                <h5 className="grey-text text-darken-3">Edit Project</h5>
                <div className="input-field">
                  <label htmlFor="title" className="active">
                    Title
                  </label>
                  <input
                    onChange={this.handleChange}
                    type="text"
                    id="title"
                    defaultValue={project.title}
                  />
                </div>
                <div className="input-field">
                  <label htmlFor="content" className="active">
                    Edit Project Content
                  </label>
                  <textarea
                    id="content"
                    onChange={this.handleChange}
                    className="materialize-textarea"
                    defaultValue={project.content}
                  />
                </div>
                <div className="input-field">
                  <button className="btn pink lighten-1 z-depth-0">
                    Update
                  </button>
                </div>
              </form>
            </div>
            <div className="card-action grey lighten-4 grey-text">
              <div>
                Posted by {project.authorFirstName} {project.authorLastName}
              </div>
              <div>{moment(project.createdAt.toDate()).calendar()}</div>
              <div className="right-align" />
            </div>
          </div>
        </div>
      );
    } else {
      return (
        <div className="container center">
          <p>Loading project...</p>
        </div>
      );
    }
  }
}

const mapStateToProps = (state, ownProps) => {
  //id = the document id of the project
  const id = ownProps.match.params.id;
  const projects = state.firestore.data.projects;
  const project = projects ? projects[id] : null;
  return {
    project: project,
    auth: state.firebase.auth,
    docId: id
  };
};

const mapDispatchToProps = dispatch => {
  return {
    editProject: (project, docId) => dispatch(editProject(project, docId))
  };
};

export default compose(
  connect(
    mapStateToProps,
    mapDispatchToProps
  ),
  firestoreConnect([
    {
      collection: "projects"
    }
  ])
)(EditProject);

После посещения страницы редактирования я бы хотел, чтобы данные оставались неизменными, если пользователь не вносит никаких изменений в поле ввода.

1 Ответ

0 голосов
/ 18 июня 2019

Мне удалось правильно обновить локальное состояние с помощью React Router для передачи реквизитов моему компоненту EditProject из его «родительского компонента».Для этого я использовал маршрутизатор React, поскольку компонент EditProject фактически не вложен в этот «родительский компонент».

Вот как вы можете передавать реквизиты другим компонентам с помощью React Router:

Укажите, куда вы хотите отправлять свои реквизиты и что вы хотите отправлять:

//ProjectDetails Component

<Link to={{
            pathname: "/edit/" + docId,
            state: {
              title: project.title,
              content: project.content
            }
            }}>
   <button className="btn">Edit</button>
</Link>


Реквизиты Aquire в методе жизненного цикла componentDidMount() и обновление локального состояния с помощью setState().

//EditProject Component (component recieving props from ProjectDetails)

class EditProject extends Component {
  state = {
    title: "",
    content: ""
  };

  componentDidMount = () => {
    //Aquire proprs from React Router
    const title = this.props.location.state.title
    const content = this.props.location.state.content

    //Update the local state
    this.setState({
      title: title,
      content: content
    })
  }

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...