redux useSelector: компонент не реагирует на обновления состояния

reactjs #redux #react-redux #react-hooks

#reactjs #redux #react-redux #реагирующие хуки

Вопрос:

Я настраиваю очень простое приложение react typescript и redux. Я использовал useSelector() для получения состояния, а затем использовал его в своем компоненте. однако, когда я подключаюсь к хранилищу, добавляя новую статью, пользовательский интерфейс не меняется, я проверил redux dev tools, и хранилище обновляется, я прочитал, что useSelector автоматически подписывается на store, поэтому я не уверен, почему у меня возникла эта проблема. мой код компонента приложения:

 function App() {
  const dispatch: Dispatch<any> = useDispatch();

  const articles: readonly IArticle[] = useSelector(
    (state: ArticleState) => state.articles
  );

  const saveArticle = React.useCallback(
    (article: IArticle) => dispatch(addArticle(article)),
    [dispatch]
  );

  return (
    <div className="App">
      <header className="App-header">
        <h1>My Articles</h1>
        <AddArticle saveArticle={saveArticle} />
        <ul>
          {articles.map((article: IArticle) => (
            <li>{article.title}</li>
          ))}
        </ul>
      </header>
    </div>
  );
}

export default App;
 

дополнительная статья ActionCreator

 export function addArticle(article: IArticle) {
  const action: ArticleAction = {
    type: actionTypes.ADD_ARTICLE,
    article,
  };

  return simulateHttpRequest(action);
}
 

Редуктор

 const reducer = (
  state: ArticleState = initialState,
  action: ArticleAction
): ArticleState => {
  switch (action.type) {
    case actionTypes.ADD_ARTICLE:
      const newState = {
        ...state,
      };
      const newArticle: IArticle = {
        id: Math.random(), // not really unique
        title: action.article.title,
        body: action.article.body,
      };
      newState.articles.push(newArticle);
      return newState;
    case actionTypes.REMOVE_ARTICLE:
      const newArticles = state.articles.filter(
        (article) => article.id !== action.article.id
      );
      return {
        ...state,
        articles: newArticles,
      };
    default:
      return state;
  }
};

export default reducer;
 

вот скриншот, на котором я вижу, что данные фактически обновляются в хранилище

введите описание изображения здесь

Комментарии:

1. Можете ли вы показать код, который «добавляет» элемент в статьи? useSelector не сработает, если экземпляр состояния не изменился.

2. кроме того, почему вы помечаете значение как «только для чтения»?

3. @JonathanAlfaro код для добавления новой статьи — это метод saveArticle

4. нет, это не так… функция, которая сохраняет статью, называется dispatch(addArticle(статья)… итак, нам нужно увидеть код для «addArticle»

5. @JonathanAlfaro Я только что отредактировал вопрос и добавил addArticle ActionCreator

Ответ №1:

Строка newState.articles.push(newArticle); изменяет существующий articles массив. Затем ваш селектор пытается прочитать state.articles . Поскольку это та же ссылка, что и раньше, React-Redux предполагает, что ничего не изменилось, и не будет повторно отображаться:

https://react-redux.js.org/api/hooks#equality-comparisons-and-updates

Пожалуйста, переключитесь на использование Redux Toolkit для настройки хранилища и логики редуктора. Это не только позволит вам упростить ваши редукторы, написав такую «мутирующую» логику и позволив ей создавать обновления неизменно, это эффективно делает случайные мутации, подобные этому, невозможными.