首页
学习
活动
专区
圈层
工具
发布

与Immer.js
EN

Stack Overflow用户
提问于 2021-09-07 18:35:16
回答 1查看 211关注 0票数 0

我有个问题要问immer.jsreactjsredux。我对reactjs很熟悉。据我所知,“不允许”通过

代码语言:javascript
复制
props.someValue= 'someValue'

因此,需要将回调函数传递给组件本身,如下所示

代码语言:javascript
复制
<SomeComponent
   key={"componentKey"}
   someValue={"someValue"}
   onSomeValueChange={this.handleSomeValueChange.bind(this)}
/>

SomeComponent中,您可以这样调用这个函数:

代码语言:javascript
复制
...
this.props.onSomeValueChange('someNewValue');
...

你可以用redux来处理这件事。

代码语言:javascript
复制
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { updateSomeValue } from '../actions/index';

function SomeComponent(props) {

    function onTextChanged(event) {
        props.updateSomeValue(event.target.value);
    }

    return (
        <>
            <input type="text" value={someValue} onChange={onTextChanged} />
        </>
    )
}

function mapStateToProps({ someValue }) {
    return {
        someValue
    };
}

function mapDispatchToProps(dispatch) {
    return {
        updateSomeValue: someValue => dispatch(updateSomeValue(someValue)),
    };
}
 
const Form = connect(
    mapStateToProps,
    mapDispatchToProps
)(SomeComponent);
 
export default Form;

上面的代码是一个非常简单的例子,因为someValue只是一个string,没有复杂的对象。现在,如果它变得越来越复杂,并且有带有子对象的对象,我仍然在寻找更新子对象的最佳方法。过去,在更新原始属性之前,我使用lodash来创建对象的“克隆”,并修改了“克隆”。

代码语言:javascript
复制
function onTextChanged(event) {
    let updatedJob = _.cloneDeep(props.currentJob);
    for(let a = 0; a < updatedJob.job_texts.length; a++) {
        if(updatedJob.job_texts[a].id === props.jobText.id) {
            updatedJob.job_texts[a].text = event.target.value;
        }
    }
    props.updateCurrentJob(updatedJob);
}

这个解决方案确实有效,但正如您所看到的,它可能不是处理此问题的最佳方法。现在我读到,我的解决方案也不推荐。据我所知,您需要创建每个子对象的“副本”。然后我偶然发现了关于reduximmer.js页面,但我不太确定如何使用这个页面:

情况如下:我有一个对象currentJob,它有几个属性。其中一个属性是一个名为array的子对象( job_texts )。一个job_text有一个属性text,我需要更新它。

我想,我能处理好,这样:

代码语言:javascript
复制
let updatedJob = props.currentJob;
props.updateCurrentJob(
    produce(updatedJob.job_texts, draftState => {
        if(draftState.id === props.jobText.id) {
            draftState.text = text;
        }
    })
);

...but当然不能工作,因为使用上面的代码,我正在用子对象数组更新currentJob。请任何人给我一个提示,我如何使用immer.js来更新对象currentJob中的一个job_text?事先非常感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-07 22:30:33

最好的方法是使用正式的Redux,它已经将immer包含在用createReducercreateSlice创建的还原器中。

这也是两年来推荐的使用Redux的方法。

通常,在还原器中也应该有“子对象更新逻辑”,而不是组件。

因此,对于RTK,例如,一个“片段”看起来就像

代码语言:javascript
复制
const objectSlice = createSlice({
  name: 'object',
  reducers: {
    updateSubObjectText(state, action) {
      const jobText = state.job_texts.find(text => text.id === action.payload.id)
      if (jobText) {
        jobText.text = action.payload.text
      }
    }
  }
})

export const { updateSubObjectText } = objectSlice.actions
export default objectSlice.reducer

这将创建一个还原器和一个动作创建者updateSubObjectText,以便在组件中使用。它们将连接在一起,操作类型是您不关心的实现细节。

在您的组件中,您现在只需执行以下操作

代码语言:javascript
复制
dispatch(updateSubObjectText({ id, text }))

有关更多信息,请参见这个快速进入到Redux工具包正式正式的“基本要素”教程,它们现在将Redux作为编写真实Redux逻辑的推荐方法。

写减速机上也有一个完整的docs页面。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69093083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档