【问题标题】:useSelector not updating when store has changed in Reducer. ReactJS Redux当 Store 在 Reducer 中发生更改时,useSelector 不会更新。 ReactJS Redux
【发布时间】:2020-03-10 01:16:13
【问题描述】:

我正在改变减速器的状态。在调试时,我检查了状态是否真的发生了变化。但是组件没有更新。

组件:

function Cliente(props) {
    const dispatch = useDispatch()
    const cliente = useSelector(({ erpCliente }) => erpCliente.cliente)
    const { form, handleChange, setForm } = useForm(null)

...

function searchCepChangeFields() {
    //This call the action and change the store on reducer
    dispatch(Actions.searchCep(form.Cep))  
        .then(() => {   
            // This function is only taking values ​​from the old state. 
            // The useSelector hook is not updating with store
            setForm(form => _.setIn({...form}, 'Endereco', cliente.data.Endereco))
            setForm(form => _.setIn({...form}, 'Uf', cliente.data.Uf))
            setForm(form => _.setIn({...form}, 'Cidade', cliente.data.Cidade))
            setForm(form => _.setIn({...form}, 'Bairro', cliente.data.Bairro))                  
        })
}

减速机:

 case Actions.SEARCH_CEP:
        {
            return {
                ...state,
                data: { 
                    ...state.data,
                    Endereco: action.payload.logradouro,
                    Bairro: action.payload.bairro,
                    UF: action.payload.uf,
                    Cidade: action.payload.cidade                    
                }
            };
        }  

【问题讨论】:

    标签: javascript reactjs ecmascript-6 react-redux react-hooks


    【解决方案1】:

    注意:你最好开始使用redux-toolkit 来防止引用 在您编写代码时,它是使用 redux 的更好且几乎是必须的方式

    您在处理对象时遇到的问题很常见, 道具不会改变,因为您正在更改对象属性,但对象本身不会从反应端改变。

    即使你给它一个全新的对象 react 没有看到属性对象发生变化,因为引用保持不变。

    你需要像这样创建一个新的引用:

    Object.assign(state.data,data);
    
    return {
      ...state,
      data: { 
        ...state.data,
        Endereco: action.payload.logradouro,
        Bairro: action.payload.bairro,
        UF: action.payload.uf,
        Cidade: action.payload.cidade                    
      }
    }
    

    要添加更多内容,您可以了解解决此问题的 Immer 库 问题。

    【讨论】:

    • 天哪!太感谢了!我m trying to solve this for more than 3 hours and I dont 看到有关此的任何信息。你只是为我节省了很多!谢谢
    • initialState = { result: [], isLoading: true, isOrderCreated: false, error: undefined }; 我的reducer没有更新这个`case PLACEORDERFAILURE: return { ...state, error: true } `有人可以帮忙
    • 是我还是 OPs 代码和这个答案没有任何区别?
    • Object.assign()中,第二个参数“data”从何而来?
    • 数据对象从何而来?
    【解决方案2】:

    没必要

    Object.assign(state.data, data);
    

    总是在更改数组或对象的数据时

    return(
      object: {...state.object, a: 1, b: 2},
      array: [...state.array, 1, 2, 3]
    )
    

    这 3 个点 (...) 确保您创建了一个新对象。在 redux 上,您必须始终创建一个新对象,而不仅仅是更新状态。这样 redux 就不会验证您的数据是否已更改。

    当有嵌套对象或数组时,是一样的

    请注意:

    initialState = {
     object: {
         ...object,
         anotherObject:{
            ...anotherObject,
            a: 1,
            b: 2
          }
       }
    }
    

    【讨论】:

    • 这样做并没有提供我不得不接受 elab AB 答案的预期结果。我尝试了各种传播操作。
    【解决方案3】:

    不知何故,无法识别 Object.assgin 用 ES6 语法更新。

    updatedConnectors = state.connectors
    

    这将创建对当前状态的引用。在 ES6 中,引入 ... 以进行新的引用。

    updatedConnectors = { ...state.connectors }
    .....
    return  {
        ...state,
        connectors: updatedConnectors
    };
    

    使用它来提取和复制新的参考。这也会触发状态变化

    20 年 9 月 27 日更新 我已经写了一些 utils 函数来处理这个,让我们试试这个

    //Utils
    export const getStateSection = ({ state, sectionName }) => {
    
      const updatedState = { ...state }
      const updatedSection = updatedState[sectionName]
      return updatedSection
    }
    
    export const mergeUpdatedSection = ({ state, sectionName, updatedValue }) => {
      const updatedState = { ...state }
      updatedState[sectionName] = updatedValue
      return updatedState
    }
    

    那么在任何reducer中,它应该像这样使用:

    //reducer
    const initState = {
      scheduleDetail: null,
      timeSlots: null,
      planDetail: {
        timeSlots: [],
        modifedTimeSlots: [],
        id: 0
      }
    
    }
    .....  
    const handlePickTimeSlot = (state, action) => {
      let planDetail = getStateSection({ state, sectionName: 'planDetail' })
      // do stuff update section
      return mergeUpdatedSection({ state, sectionName: 'planDetail', updatedValue: planDetail })
    }
    

    【讨论】:

    • 你的代码是什么?您是否在返回状态添加了 ...?
    • 是的,我必须先创建一个新对象,然后再更新它。 ... 还不足以触发更新。
    • @JasonG 这是 ES6 的调用扩展对象。您可以搜索此关键工作并获得想法。这涉及到 JS 的内存处理。这种方式总是对我有用。你使用的是哪个版本的 React
    • 这也没有提供所需的结果。不管有多少种不同的传播方式,我都必须接受 elab AB 的回答。
    【解决方案4】:

    因为 elab BA 的编辑队列已满。

    这里接受的答案是他所说的数据存在的意思

    case MYCASE:
      let newDataObject = Object.assign(state.data, {...action.payload});
      // or 
      // let newDataObject = Object.assign(state.data, {key: 'value', 'key2': 'value2' ...otherPropertiesObject);
      return {
        ...state,
        ...newDataObject
      }
    
    

    【讨论】:

      猜你喜欢
      • 2018-08-09
      • 2018-09-27
      • 2020-10-21
      • 1970-01-01
      • 2020-05-01
      • 2019-02-16
      • 2019-07-18
      • 2020-09-25
      • 1970-01-01
      相关资源
      最近更新 更多