最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to pass nested properties with spread attributes correctly? (JSX) - Stack Overflow

programmeradmin2浏览0评论

#1

Hello. I have the code:

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"

Why do I get 1 variable reference for 2 separate components instead of 2 instances of nested.prop for every component? Why this.props saves only last setted value for all instances of the component after mounting? Is it a normal behavior? I think the correct behavior is having different property values for different instances.

P.S. I have tested this code here.

#2

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

My next question: How to pass nested properties without a manual mutation of props?

For example:

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

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

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

Guide to the code above JSX spread attribute feature just override props.nested and I lose default nested properties. But it is not that I need. How about to implements a recursive traversing of nested objects in stage of JSX spread attributes parsing?
Or Is there some useful pattern for this case?

#1

Hello. I have the code:

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"

Why do I get 1 variable reference for 2 separate components instead of 2 instances of nested.prop for every component? Why this.props saves only last setted value for all instances of the component after mounting? Is it a normal behavior? I think the correct behavior is having different property values for different instances.

P.S. I have tested this code here.

#2

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

My next question: How to pass nested properties without a manual mutation of props?

For example:

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

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

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

Guide to the code above JSX spread attribute feature just override props.nested and I lose default nested properties. But it is not that I need. How about to implements a recursive traversing of nested objects in stage of JSX spread attributes parsing?
Or Is there some useful pattern for this case?

Share Improve this question edited Jan 22, 2021 at 18:19 Guilherme Samuel 5496 silver badges13 bronze badges asked Mar 28, 2016 at 15:34 Kirill A. KhalitovKirill A. Khalitov 1,2654 gold badges17 silver badges25 bronze badges 5
  • 1 Please ask a fully qualified question here as links can die. – Naftali Commented Mar 28, 2016 at 15:35
  • Here are tips how to ask a good question on SO: stackoverflow.com/help/how-to-ask – crackmigg Commented Mar 28, 2016 at 15:37
  • "how to pass nested properties" foo(a.nested.property) ? – Felix Kling Commented Mar 28, 2016 at 15:39
  • OK. Just later when I will be at home with my PC. – Kirill A. Khalitov Commented Mar 28, 2016 at 15:40
  • I do not understand what you want to achieve with your code. Why do you try to store the props in other props? What do you want to do with that later? – Nicole Commented Mar 28, 2016 at 20:12
Add a comment  | 

1 Answer 1

Reset to default 22

This is actually a good question!

Short answer: you can't do deep merge with spread operator - it only does shallow merging. But you surely can write function that will do objects traversing and implements deep merging.

This actually leaves you 3 options:

1) Just don't do deep merge. If you have 2 level nested object you can do such simple thing:

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

Shallow merging force you to say explicitly that you will have new value of nested property. Which is a good thing as it makes your code obvious. You can also try out runnable examples here.

2) You may use a library for immutable structures. F.e. immutable.js. With it your code will look pretty similar.

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) You may use deep merge: find some implementation in npm or write it yourself and you will have a code like this(again immutable.js as an example):

const finalProps = oldProps.mergeDeep(newProps);

You may want this in some cases, but such code makes update operation implicit and it rises a lot of problems which are listed greatly here

发布评论

评论列表(0)

  1. 暂无评论