Vencovsky
Vencovsky

Reputation: 31625

Change a prop value inside functional component can cause problems in react component?

If I receive a prop and change it in my functional component, can it create a problem? Or it's ok to change it inside the component?

e.g

const MyComponent = ({ foo }) => {

    // is this bad?
    foo = someCondition ? bar : foo

    return (...)
}

I know that I could create another variable and store the values, but I would like to know if changing the prop it self won't cause any problem because it's a functional component.

Upvotes: 2

Views: 4532

Answers (5)

pope_maverick
pope_maverick

Reputation: 980

const MyComponent = ({ foo }) => {

    // Not valid
    foo = someCondition ? bar : foo

    return (...)
}

There are two kinds of data in React,

a)Props(immutable data) b)State(mutable data)

you are not supposed to change the immutable data(there are some ways to do it, but not recommended). what you should do is, (you can't assign a callback and change from here, i'll explain later why)

if you want to just use just the value inside this component

const baz = foo === condition ? bar : foo

or render something based on foo meets some condition

return (
 <div>
  {foo === somecondition ? <A /> : <B />}
 </div>

 )

Or you want to actually change it,

coming from a global state like redux or mobx,

u should change it from the reducers in case of redux or @action decorated functions in mobx.

if it's a local state which passed down to the child component,

u can set a call back and assign to a click handler in which the case it is feasible

handleClick = () => {
 this.setState(prevState => ({
  ...prevState,
  foo: someCondition ? bar : foo,
 }))
}

render () {
 const { handleClick } = this

 return <ChildComponent {...{ handleClick }} />
}

Like said before u can't change the passed down local state from render of the child(or render of any component[actually u can, but may end up in infinite loops: each time a state change happens, the component will re render, so the loop(pure components excluded eg: shouldComponentUpdate() hook which validates an unrelated condition)])

in such cases what u should do is to make the child component also a stateful component and change the parent props with a callback

class Child extends Component {
 //set once 
 componentWillMount() {
  if (condition) callback
 }

 //whenever there is change
 componentWillReceiveProps(nextProps) {
  if (condition) callback
 }

 //use correct lifecycle method which meets your requirement..
}

Upvotes: 1

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20944

No, it shouldn't create any problems. As with regular functions the arguments passed are their own variables in the function scope and don't mutate the original value passed to the function.

function something(value) {
  value = 'nothing';
}

var anything = 0;
something(anything);

// Anything should still be 0;
console.log(anything);
But I would suggest to not mutate your variables.

Upvotes: 4

Robert Andrei
Robert Andrei

Reputation: 297

If foo in your example is passed from the parrent, and the parrent keeps it in its state, then you would also need to pass setFoo as a paramater to your component and use that to update it properly.

function Parrent(){  
  let [foo, setFoo] = useState('foo');  
  return <Child foo={foo} setFoo={setFoo}/>
}

As for changing the props directly, you can if they are arrays or objects.

Upvotes: 2

Peter Ambruzs
Peter Ambruzs

Reputation: 8213

I avoid changing the prop. But I created a simple example and changing the prop in the children do not affected the value in the parent component.

https://codesandbox.io/s/objective-cdn-cq55d

I tested it with several render. Thats why I added an input. Typing in it makes the component rerender.

Upvotes: 1

Ali Torki
Ali Torki

Reputation: 2028

Props in the React are just read-only variables. You should change the props values by the parent component

Upvotes: 1

Related Questions