34

I am receiving props in my component. I want to add a property 'LegendPosition' with the props in this component. I am unable to do that. Please help me with this. I have tried this code yet but no success:

var tempProps     = this.props;
tempProps.legendPosition = 'right';
Object.preventExtensions(tempProps);

console.log(tempProps);
Ankit Kaushal
  • 913
  • 2
  • 9
  • 16

7 Answers7

33

You can't modify this.props. Here tempProps is reference of this.props so it does not work. You should create a copy of the props using JSON.parse() and JSON.stringify()

var tempProps = JSON.parse(JSON.stringify(this.props));
tempProps.legendPosition = 'right';
Object.preventExtensions(tempProps);

console.log(tempProps);

For a better and efficient way to deep clone object see What is the most efficient way to deep clone an object in JavaScript?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • So instead of closing it as a duplicate you're adding one of the answers from said duplicate as your own... – Andreas Apr 08 '19 at 06:35
  • @Andreas The question is not how to copy the object. The question is why props without cloning doesnot mutate. If he would have visited the question he would have this problem solved – Maheer Ali Apr 08 '19 at 06:36
  • @MaheerAli your code was working, but my child component not getting the updated props. I don't know why. Please check your edited answer – Ankit Kaushal Apr 08 '19 at 07:03
  • 2
    @AnkitKaushal You can't change `props`. props can only be updated by the parent of the component. You can change `tempProps` and use `tempProps` inside render method or where ever you want to display the `props` – Maheer Ali Apr 08 '19 at 07:13
  • Okay. @MaheerAli . I will try to use tempProps then. Thank you for your help – Ankit Kaushal Apr 08 '19 at 07:43
9

props is not mutable, you cant "add" anything to them. if you want to "copy" them then you need to do

const tempProps = {...this.props};

And the only reason i can see you needing to add more props is to pass it down to a child, but you can do that without adding it to the props object.

EDIT: add props with extra prop

<Component {...this.props} legendPosition="right" />
Joey
  • 1,075
  • 8
  • 13
  • note: this is a shallow copy, I wouldn't advise NOT doing a deep copy since it messed up any kind of optimisations react would attempt. – Joey Apr 08 '19 at 06:34
  • has provided a better way of copying the object. – Ronit Mukherjee Apr 08 '19 at 06:34
  • @Joey Yes, I want to send the updated props to a child component, If it is possible without copying or cloning to a new object, Please help me how can I achieve this. – Ankit Kaushal Apr 08 '19 at 07:01
3

I want to send the updated props to a child component, If it is possible without copying or cloning to a new object, Please help me how can I achieve this.

Solution is as simple as:

<ChildComponent {...this.props} legendPosition="right" />

Of course legendPosition will be available in ChildComponent by this.props.legendPosition.

Of course earlier this.props can contain already legendPosition property/value which will be overwritten by defined later - order matters.

Of course there can be many spread operators - for multiple properties, logic blocks ... whatever:

const additonalProps = {
  legendPosition: 'right',
  sthElse: true
}
return (
  <ChildComponent {...this.props} {...additonalProps} />
)
xadm
  • 8,219
  • 3
  • 14
  • 25
2

below in tempProps object spread operator copy your this.props object and after spread operator we can add new object property or we can update existing object property.

var tempProps = {
  ...this.props,
  tempProps.legendPosition = 'right' //property you want to add in props object
};
iambinodstha
  • 937
  • 10
  • 11
1

Your answer is in this line.

var tempProps = this.props;

this.props is immutable that means you can not change the property value in function. you can use a this.state so you can modify it in your function

  1. props --- you can not change its value.
  2. states --- you can change its value in your code, but it would be active when a render happens.
Negi Rox
  • 3,828
  • 1
  • 11
  • 18
1

For anyone getting this error with jest, make sure to mock your component this way:

jest.mock('component/lib', () => ({
  YourComponent: jest.fn()
}))

Then in your test you can mock the implementation:

(YourComponent as jest.Mock).mockImplementation(() => <div>test</div>);

Hope this works

0

You can define default values for your props properly by assigning to the special defaultProps property:

https://reactjs.org/docs/typechecking-with-proptypes.html

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

// Specifies the default values for props:
Greeting.defaultProps = {
  name: 'Stranger',
};
do7
  • 21
  • 3