如何正确传递具有扩展属性的嵌套属性?(JSX)

IT技术 javascript reactjs jsx
2021-05-02 22:17:53

#1

你好。我有代码:

class Component extends React.Component {
    render() {
        this.props.nested.prop = this.props.parse.nested.prop;
        return <div>Component</div>;
    }
    componentDidMount() {
        console.log(this.props.nested.prop);
    }
}
Component.defaultProps = {
    nested: {
        prop: "default",
    },
};

const obj1 = {
    nested: {
        prop: "obj1",
    },
};
const obj2 = {
    nested: {
        prop: "obj2",
    },
};

class Application extends React.Component {
    render() {
        return (
            <div>
                <Component parse={obj1} />
                <Component parse={obj2} />
            </div>
        );
    }
}

React.render(<Application />, document.getElementById("app"));
// console output:
// "obj2"
// "obj2"

为什么我会为 2 个单独的组件获得 1 个变量引用,而不是为每个组件获得 2 个 Nested.prop 实例?为什么 this.props 在挂载后只保存组件所有实例的最后设置值?这是正常行为吗?我认为正确的行为是对不同的实例具有不同的属性值。

PS 我在这里测试了这段代码

#2

jimfb已回答: "You are mutating the default prop that was passed in. The line this.props.nested.prop = this.props.parse.nested.prop; is illegal."

我的下一个问题: How to pass nested properties without a manual mutation of props?

例如:

Component.defaultProps = {
    nested: {
        prop1: "default",
        prop2: "default",
    },
};

const props = {
    nested: {
        prop1: "value",
    },
};

let component = <Component {...props} />;

上面 JSX 扩展属性功能的代码指南只是覆盖了 props.nested 并且我丢失了默认的嵌套属性。但这不是我需要的。如何在JSX扩展属性解析阶段实现嵌套对象的递归遍历?
或者对于这种情况有一些有用的模式吗?

1个回答

这其实是个好问题!

简短回答:您不能使用扩展运算符进行深度合并 - 它只能进行浅层合并。但是您肯定可以编写将执行对象遍历并实现深度合并的函数。

这实际上给您留下了 3 个选项:

1)只是不要进行深度合并。如果你有 2 级嵌套对象,你可以做这样简单的事情:

const newNested = {...oldProps.nested, ...newProps.nested };
const finalProps = { ...oldProps, nested: newNested };

浅合并迫使明确说明您将拥有新的嵌套属性这是一件好事,因为它使您的代码显而易见。您还可以在此处试用可运行的示例

2)您可以将库用于不可变结构。Fe immutable.js有了它,您的代码将看起来非常相似。

const oldProps = Immutable.fromJS({
  nested:
  {
    prop1: "OldValue1",
    prop2: "OldValue2",
  }
});

const newProps = Immutable.fromJS({
  nested:
  {
    prop1: "NewValue1",
  }
});

const finalProps = oldProps.updateIn(['nested'], (oldNested)=>
  oldNested.merge(newProps.get('nested'))
)

3)你可以使用deep merge:在npm中找到一些实现或者自己编写,你会得到这样的代码(再次以immutable.js为例):

const finalProps = oldProps.mergeDeep(newProps);

在某些情况下您可能需要这样,但是这样的代码使更新操作隐含,并且引起了很多问题,这里列出了很多