При использовании React / Redux, как диспетчеризировать действие, которое просто изменяет состояние Redux, по сравнению с выполнением какой-либо задачи? - PullRequest
1 голос
/ 29 февраля 2020

Для официального Redux asyn c приложения , когда пользователь хочет увидеть Reddit topi c из "reactjs", "frontend" или "redux js", отправка просто отправляет объект действия:

{
  type: SELECT_SUBREDDIT,
  subreddit: 'frontend'
}

и затем позволяет componentDidUpdate(prevProps) обрабатывать «побочный эффект» извлечения данных.

Я бы сделал это, не отправляя действие , но отправляя функцию:

dispatch(
    dispatch => {
        fetch(`https://www.reddit.com/r/${topic}.json`)
            .then(response => response.json())
            .then(data => {
                dispatch({
                    type: "GOT_DATA",
                    data: data
                })
            });
    }
)

Я думал, что мой подход более прост, и если использовать componentDidUpdate() для создания побочного эффекта, компонент не будет визуализирован три раза? Первый для изменения топи c, второй раз для отправки состояния выборки (и с кодом для извлечения данных) и третий раз, когда данные возвращаются.

Этот подход на самом деле довольно интересно: сначала нужно «просто изменить состояние приложения, и я ничего не буду делать», а затем в коде жизненного цикла компонента класса (или в useEffect() компонента функции) это так, «когда подпорки которые приходят (из состояния), говорят, что что-то должно быть сделано, я сделаю это, и при необходимости изменим больше состояния. "

Кроме того, первый способ сделать что-то, если мы посмотрим на исходный код , имеет так много состояний и условий. Это всего лишь простой пример получения некоторых тем Reddit. Что если существует 7 состояний и условий, то код будет настолько насыщен условиями, что обработка этого состояния истинна, а этого состояния нет, а третье состояние истинно и т. Д. c? Это может быть 2⁷ комбинации, и код так тесно связан - если менеджер просит изменить какое-либо поведение, это похоже на то, что программист должен переподключить все и проверить все условия, все действия, всю диспетчеризацию и т. Д. c. Это похоже на спагетти состояний и условий.

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

Конечно, это показывает «Загрузка ... "и может кэшировать данные, и может разрешить refre sh ... но даже если это делается с помощью императивного кода, это может быть на самом деле более короткий код, и он более прямой и его легче понять .

Я бы хотел знать, какие могут быть методы: должны ли мы, или в лучшем случае, следовать примеру исходного кода кода, или мы можем сделать это вторым методом, как описано выше - разве не рекомендуется отправлять функцию, которая выполняет асинхронную обработку c или "побочный эффект"?

1 Ответ

1 голос
/ 29 февраля 2020

И ваш подход, и их подход включают в себя отправку функции, которая будет обрабатываться при помощи избыточного числа. Часть, которая делает это немного более интересным, состоит в том, что есть две вещи, которые необходимо сделать:

  • Немедленно обновить, какой subreddit помечен как выбранный (это значение используется в приложение. js строка 42)
  • Загрузить данные для этого подредакта

Есть несколько способов сделать это. Вариант 1: отправьте действие, чтобы обновить выбранный субкредит, затем отдельно отправьте действие, чтобы выполнить выборку. Что-то вроде:

handleChange = (nextSubreddit) => {
  this.props.dispatch(selectSubreddit(nextSubreddit));
  this.props.dispatch(fetchPostsIfNeeded(nextSubreddit));
}

Это работает, но имеет уязвимость. Что если я отправлю один, но забуду отправить другой? Тогда у меня будет приложение в несовместимом состоянии. Возможно, это не большая проблема, если это единственное место в коде, где мы это делаем, но выгода от избыточности возникает в сложных приложениях, где несколько частей приложения могут взаимодействовать с состоянием, и им не нужно путать друг друга. Поэтому для более сложного приложения я бы не хотел, чтобы разработчик знал, что за отправкой одного всегда следует отправка другого.

Вариант 2: Поместите диспетчеризацию действия select внутри ствола

export const fetchPostsIfNeeded = subreddit => (dispatch, getState) => {
  dispatch(selectSubreddit(subreddit);
  if (shouldFetchPosts(getState(), subreddit)) {
    return dispatch(fetchPosts(subreddit))
  }
}

// ... elsewhere:

handleChange = (nextSubreddit) => {
  this.props.dispatch(fetchPostsIfNeeded(nextSubreddit));
}

Этот подход является улучшением в том смысле, что теперь существует единственная точка входа, которая обеспечит выполнение обеих вещей. Но на самом деле все еще возможно отправить selectSubreddit самостоятельно. Мы создали способ отправки обоих одновременно, но старый способ все еще существует.

Вариант 3. Использование изменения состояния в качестве индикатора для извлечения данных.

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

Одним из недостатков этого является то, что компонент должен быть смонтирован, чтобы начать выборку. Это не частая проблема, так как если она не смонтирована, зачем вам вообще нужны данные? Но это может быть проблемой, если есть несколько компонентов, которые хотят использовать данные, так как вы можете быть вынуждены продублировать логи извлечения c во всех компонентах. Если это проблема, я, вероятно, вернусь к варианту 2.


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

...