Как заменить компонент WillRecieveProps - PullRequest
0 голосов
/ 19 октября 2018

Я новичок в редуксе и последовал этому руководству , чтобы создать простое приложение для блогов с реагированием и редукцией.Я закончил это, однако я заметил, что componentWillRecieveProps является устаревшим .Я пытаюсь заменить его более новым кодом, но не смог понять, как это сделать.Я прочитал эту статью о замене 'componentWillReceiveProps' на 'getDerivedStateFromProps', но я не думаю, что это правильное использование для getDerivedStateFromProps в качестве Реагировать в блоге при замене одного надругой описывает.

Мой текущий componentWillRecieveProps код:

import axios from "axios";
import React from "react";
import { connect } from "react-redux";

class Form extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            title: "",
            body: "",
            author: ""
        };

        this.handleChangeField = this.handleChangeField.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    //This is deprecated
    componentWillReceiveProps(nextProps) {
        console.log(this);
        if (nextProps.articleToEdit) {
            this.setState({
                title: nextProps.articleToEdit.title,
                body: nextProps.articleToEdit.body,
                author: nextProps.articleToEdit.author
            });
        }
    }


    handleSubmit() {
        const { onSubmit, articleToEdit, onEdit } = this.props;
        const { title, body, author } = this.state;

        if (!articleToEdit) {
            return axios
                .post("http://localhost:8000/api/articles", {
                    title,
                    body,
                    author
                })
                .then(res => onSubmit(res.data))
                .then(() => this.setState({ title: "", body: "", author: "" }));
        } else {
            return axios
                .patch(
                    `http://localhost:8000/api/articles/${articleToEdit._id}`,
                    {
                        title,
                        body,
                        author
                    }
                )
                .then(res => onEdit(res.data))
                .then(() => this.setState({ title: "", body: "", author: "" }));
        }
    }

    handleChangeField(key, event) {
        this.setState({
            [key]: event.target.value
        });
    }

    render() {
        const { articleToEdit } = this.props;
        const { title, body, author } = this.state;

        return (
            <div className="col-12 col-lg-6 offset-lg-3">
                <input
                    onChange={ev => this.handleChangeField("title", ev)}
                    value={title}
                    className="form-control my-3"
                    placeholder="Article Title"
                />
                <textarea
                    onChange={ev => this.handleChangeField("body", ev)}
                    className="form-control my-3"
                    placeholder="Article Body"
                    value={body}
                />
                <input
                    onChange={ev => this.handleChangeField("author", ev)}
                    value={author}
                    className="form-control my-3"
                    placeholder="Article Author"
                />
                <button
                    onClick={this.handleSubmit}
                    className="btn btn-primary float-right"
                >
                    {articleToEdit ? "Update" : "Submit"}
                </button>
            </div>
        );
    }
}

const mapDispatchToProps = dispatch => ({
    onSubmit: data => dispatch({ type: "SUBMIT_ARTICLE", data }),
    onEdit: data => dispatch({ type: "EDIT_ARTICLE", data })
});

const mapStateToProps = state => ({
    articleToEdit: state.home.articleToEdit
});

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Form);

Полный репо Codesandbox

Если componentWillRecieveProps устарела, как мне обновить мой код?

Редактировать: используя getDerivedStateFromProps, nextProps по-прежнему имеет предыдущие значения, поэтому при возврате объекта состояние возвращается к предыдущему состоянию, обновления фактически не выполняются.

Попытка использовать значения prevStateв этом случае не работает, поскольку все начальные значения prevState представляют собой пустые строки, которые вызываются и переводятся в состояние каждый раз, когда компонент выполняет рендеринг, что происходит при начальной загрузке страницы и при нажатии кнопки редактирования.

    static getDerivedStateFromProps(nextProps, prevState) {
    if (
        JSON.stringify(nextProps.articleToEdit) !==
        JSON.stringify(prevState.articleToEdit)
    ) {
        console.log(nextProps);
        console.log(prevState);
        return {
            title: nextProps.articleToEdit.title,
            body: nextProps.articleToEdit.body,
            author: nextProps.articleToEdit.author
        }; // <- is this actually equivalent to this.setState()?
    } else {
        return null;
    }
}

Ответы [ 3 ]

0 голосов
/ 19 октября 2018

Мой совет - прислушаться к предупреждению, которое React дает нам, заменив этот метод жизненного цикла из-за его неправильного использования - они говорят нам делать это только в случае необходимости, потому что, возможно, есть лучший способ (включая более новую getDerivedStateFromProps).

Из того, что я собираю в этом коде, вы визуализируете форму, позволяющую пользователю взаимодействовать с ней, но в некоторых случаях вы заменяете входные данные пользователей реквизитом.(перезаписывает состояние компонента).Легко понять, почему это анти-шаблон, но его сложно перестроить, не зная больше о приложении.

Я бы предложил переместить значения входов в родительское состояние (или создать нового родителя).и измените на value={props.title} и т. д. Если есть родитель, который контролирует состояние формы в любых обстоятельствах, вы также можете постоянно сохранять там состояние формы.

0 голосов
/ 19 октября 2018

Alrighty.Вот рабочий пример для вашего приложения.Я полностью переписал его структуру, чтобы каждый компонент обрабатывал свой собственный набор состояний и реквизитов.Компоненты также можно использовать повторно, поэтому их можно размещать где угодно - при условии, что для них требуются реквизиты.

Примечания:

  1. Не смешивайте .jsx и .js (см.шаг 6 для исправления)
  2. Отделите компоненты контейнера от ваших компонентов .Также создавайте повторно используемые компоненты - это значительно упрощает ваше состояние и логику поддержки.
  3. Для вашего приложения вы можете полностью удалить избыточность и вместо этого позволить своему серверу быть «источником правды».Таким образом, вместо сохранения в состояние избыточности и манипулирования состоянием избыточности, вы просто делаете AJAX запросов на использование API для CRUD с вашим articles (например, отправка формы отправит запрос post на API, который добавит статью в БД, затем либо перенаправит пользователя обратно на /articles, либо он может просто вернуть все статьи после публикации и обновить состояние ShowArticles новыми данными).До вас, как вы хотите справиться с этим.Но, с учетом вышесказанного, единственное время, когда вам действительно нужен редукс, это если вы делитесь реквизитами из двух отдельных сильно вложенных компонентов.
  4. Если вы используете редукс, добавьте папки types и actions, как показано например ниже.Это делает ваш код более легким для чтения и более модульным.
  5. Избегайте использования index.js, если в корневой папке нет только одного файла.В противном случае, когда приложение сломается (и оно будет), вам будет сложно выяснить, какой "index.js" сломался, если их много.
  6. Шаблон, который вы используете, довольно старый, и выусложняешь свою жизнь, используя её.Я создал MERN Fullstack Boilerplate , который позволяет такие вещи, как: толстые функции стрелок в методах классов, импорт scss / css node_module, импорт модулей scss уровня компонентов, одновременное выполнение server и client,ошибка наложения, выделения и многое другое.Я настоятельно рекомендую перенести на него то, что у вас есть.

Рабочий пример: https://codesandbox.io/s/4x4kxn9qxw (к сожалению, шаблон create-react-app не позволяет импортировать модуль scss ... охну, вы поняли)

0 голосов
/ 19 октября 2018

Метод componentWillReceiveProps () устарел, введя новый метод жизненного цикла, называемый getDerivedStateFromProps ().

Помните, что вы всегда должны сравнивать текущие реквизиты с предыдущими реквизитами, как показано ниже, и если они оба не совпадают, тоделайте setState, иначе вы получите бесконечное предупреждение setState

Замените приведенный ниже код вместо метода componentWillReceiveProps

   static getDerivedStateFromProps(nextProps,  prevState)  {
          //Below I used JSON.stringify to compare current props with previous props of articleToEdit object
          if (JSON.stringify(nextProps.articleToEdit) !== JSON.stringify(prevState.artileToEdit)){
        return({
            title: nextProps.articleToEdit.title,
            body: nextProps.articleToEdit.body,
            author: nextProps.articleToEdit.author
        });// <- this is setState equivalent
       }
       return null;
   }

Edit:

Вы не можете получить доступ к this.props внутри функции getDerivedStateFromProps,Если вы хотите получить доступ к некоторым предыдущим реквизитам (например, для сравнения) внутри функции, то вы можете отразить такие значения внутри состояния.Затем вы можете сравнить nextProps со значением, хранящимся в состоянии, как указано выше

Проверьте этот поток для лучшего понимания

https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props

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