Redux - ReactJS 应用程序不会重新渲染(尽管 JSON.parse 用于新对象)

Posted

技术标签:

【中文标题】Redux - ReactJS 应用程序不会重新渲染(尽管 JSON.parse 用于新对象)【英文标题】:Redux - ReactJS app does not rerender (although JSON.parse for new object) 【发布时间】:2020-09-13 02:12:19 【问题描述】:

我有一个带有过滤器的 ReactJS 应用程序,并使用 RESET 函数来重置这些过滤器。

我也使用:Redux、Redux Persist 和 React-router-dom。

如果我看一下 Redux Devtools,它似乎可以工作。但应用无法正确重新渲染,需要刷新 (f5)。

我想要实现的目标:用 initialState 对象覆盖已配置的Filters 对象。

这是我的根减速器:

const rootReducer = (state = initialState, action) => 
  let newState = state;
  if (action.type === 'RESET_FILTERS') 
    storage.removeItem('persist:configuredFilters');
    // eslint-disable-next-line no-param-reassign
    newState =  ...newState,
      configuredFilters: JSON.parse(JSON.stringify(initialState.configuredFilters))
    ;
  
  return appReducer(newState, action);
;

这是差异(我之前配置了两个国家):

这里是对象(页面加载时的初始状态):

组件是用这个组件创建的:

/* eslint-disable max-len */
import React from 'react';
import  useSelector, shallowEqual, useDispatch  from 'react-redux';
import  Form, Select  from 'antd';
import PropTypes from 'prop-types';
import RenderTag from './RenderTag';
import * as Action from '../../store/configuredFilters/actions';

const propTypes = 
  data: PropTypes.shape(
    name: PropTypes.string.isRequired,
    label: PropTypes.string,
    placeholder: PropTypes.string,
    options: PropTypes.arrayOf(PropTypes.shape()),
  ).isRequired,
;


const  Option  = Select;


const useData = () => 
  const dataFromRdx = useSelector(
    (state) => (
      configuredFilters: state.configuredFilters,
    ),
    shallowEqual
  );
  return  dataFromRdx ;
;

const FixedListSelect = (
  data: 
    name, label, placeholder, options,
  ,
) => 
  const  dataFromRdx  = useData();

  const 
    configuredFilters: 
      data: 
        search: searchTerm,
      ,
    ,
   = dataFromRdx;


  const dispatch = useDispatch();
  const dispatchFns = 
    setConfiguredFilters: (key, value) => 
      dispatch(Action.setConfiguredFilters(key, value));
    ,
  ;

  const setRdxVal = (id, currVal) => 
    dispatchFns.setConfiguredFilters(id, currVal);
  ;

  const isFullTextSearchMode = (searchTerm && searchTerm.length);
  return (
    <Form.Item
      name=name
      label=label
      fieldKey=name
    >
      <Select
        allowClear
        disabled=isFullTextSearchMode
        showSearch
        tagRender=RenderTag
        mode="multiple"
        placeholder=placeholder
        optionFilterProp="children"
        filterOption=(input, option) => option.children.toLowerCase().includes(input.toLowerCase())
        onChange=(currVal) =>  setRdxVal(name, currVal); 
      >
        (options || []).map((el) => <Option data-filterid=el.val key=el.val value=el.val>el.label</Option>)
      </Select>
    </Form.Item>
  );
;
FixedListSelect.propTypes = propTypes;
export default FixedListSelect;

对该组件的调用:

<FixedListSelect data=
          name: 'companies',
          label: t('companies'),
          placeholder: t('companies-placeholder'),
          options: companies,
        
        />

有人可以帮忙或至少给个提示吗?

【问题讨论】:

reducer 不会触发组件的新渲染,它只会负责更新状态。你能告诉我们应该重新渲染的组件吗? 你能不能也显示appReducer 这可能与实际问题完全无关 - 但您的 rootReducer 不是一个纯函数(它改变了一个名为 storage 的外部变量 - 我猜这是本地存储?),还有这个是你永远不应该做的事情。 reducer 应该采取行动和当前状态并返回新状态,没有副作用。 您似乎正在从商店中选择具有深度状态的对象。 useSelector 的第二个参数是默认的 deepEqual,你有没有试过不用 shallowEqual 替换它? state.configuredFilters 很浅 state.configuredFilters.data.contries 例如很深,因此不会导致重新渲染,除非您使用 deepEqual。 你在你的 reducer 中处于最明确的变异状态。这会导致您的应用不响应状态更新 【参考方案1】:

在 ReactJS 中你不能直接改变状态。在 Redux 中也是如此。您必须复制现有信息。如果发现差异,Redux 会将当前树与新信息进行比较,然后更新存储并呈现新结果。如果直接变异,您将始终刷新以使其正常工作。

更多信息

Immutable Update Patterns

【讨论】:

以上是关于Redux - ReactJS 应用程序不会重新渲染(尽管 JSON.parse 用于新对象)的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS表单应用程序:如何阻止父组件重新渲染? /使用redux共享状态的正确方法

当在 ReactJs React-Redux 中仅创建或更新列表中的一个项目时,如何停止重新渲染整个项目列表?

如何使用 reactjs 和 redux 处理导航

在没有 Redux 的情况下难以在 REACTjs 中执行 GET 请求

React---路由跳转

Redux/Flux(使用 ReactJS)和动画