Problem passing an array throught props in React [duplicate] - javascript

I've been reading React's Quick Start documentation;
Whether you declare a component as a function or a class, it must never modify its own props
This is a "pure" function, because it doesn't attempt to change its inputs, and always returns the same result for the same inputs:
function sum(a, b) {
return a + b;
}
This in an "impure" function, because it changes its own input:
https://codesandbox.io/s/9z38xv4x7r
function SayHi(props) {
props.name = "Jim"; // TypeError Cannot assign to read only property 'name' of object '#<Object>'
return <h1>Hi {props.name}!</h1>;
}
Why are React props read-only?

A component should manage its own state, but it should not manage its own props. props is essentially "state that is managed by the component owner." That's why props are immutable.
React docs also recommends to treat state as if it's immutable.
That is because by manipulating this.state directly you are circumventing React’s state management, which can be potentially dangerous as calling setState() afterwards may replace the mutation you made.

You may think of React component as a function of its props and state. As you advance through the docs, you'll find that this is the case, as most functions in the React component life cycle have signatures of the form (prop, state) => { //code }.
React docs define props as any arbitrary input given to a component, and the component will render something based on the props ( and sometimes based on state too, if it is a stateful component ). So props is like something that is given to the component for say, reference. Imagine it this way: you are a component, and your parent component gives you a reference book, containing some rules on how you must behave ( a.k.a. render ). Two cases may arise:
You are dumb (stateless): You just read the book, and behave so.
You are smart (stateful): You read the book, and then note some things in your notepad, that you may view, update or delete. You may even take copy down content from the book to your notepad, and then edit the notepad.
Either way, you may not update the reference book given to you. Only the parent component can update it ( example, give you another book, or change its content ).
I don't know if this is a correct representation, but React components work in a similar way. You'll get the hang of it soon. Make sure you read Thinking in React too. Happy coding!

The props of a react component is aimed to store values and functions from its parent component. It's just the pattern, props are immutable. If you want to have a variable that would be mutable, then store it in the state of the component. States are mutable.

Related

Best practice in assigning a new key/value pair into a nested object

Im using React. and trying to assign an new key value. pair into the object. So first it goes through an if check and if it meets the requirement, I want to add the key value 'author'
if (field.component === 'Author') {
this.props.writer.config.payload.name = 'Jefferson';
console.log(this.props)
}
There are some online articles that tell me to do this way and others that tell me to do Object.assign. Basically though, I just want to add the 'name':'Jefferson' into the object.
See this answer https://stackoverflow.com/a/24943743/1964636
Mutating props in a child component is an anti pattern,
You may want to pass a function as props that can lift state in the child component.
Once you modify the state of it's parent component (assuming the props are part of the parent component's state), it will rerender with updated props.

React.js Ref Usage

I'm trying to understand usage of the Ref in React. I saw an example in the Ant Design documentation. https://3x.ant.design/components/tag/#components-tag-demo-control
There is a one line code that I couldn't get how it works.
saveInputRef = input => (this.input = input);
And usage as follows:
<Input ref={this.saveInputRef} ...
But in the React documentation, it is said that you create a ref using React.createRef() method.
https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-dom-element
Is it an alternative way of using it? Why there is no React.createRef() method?
As far as I know there are 2 different kind of Refs, but they are commonly used together.
A. There is "Ref" created by "createRef" (or "useRef" when using hooks);
This stores a value in the "current" property of the Ref. This value won't cause rerenders and is kept after rerenders.
B. And there is ref as a property of build-in components. This property is used to access the domnode.
Usually ref (B) is stored in a Ref (A)
You can, however, store whatever you'd like in Ref (A).
And you don't need necessarily need to store a node gotten from ref (B) in a Ref (A), you can access it directly as well, that what this piece of code does:
<div ref={node => doSomething(node)}/>
Or simply
<div ref={doSomething}/>
This is called a "callback Ref":
Callback Refs
React also supports another way to set refs called “callback refs”, which gives more fine-grain control over when refs are set and unset.
Instead of passing a ref attribute created by createRef(), you pass a function. The function receives the React component instance or HTML DOM element as its argument, which can be stored and accessed elsewhere.
https://reactjs.org/docs/refs-and-the-dom.html#callback-refs
EDIT:
more about Ref (A) when using hooks.
Essentially, useRef is like a “box” that can hold a mutable value in its .current property.
You might be familiar with refs primarily as a way to access the DOM. If you pass a ref object to React with , React will set its .current property to the corresponding DOM node whenever that node changes.
However, useRef() is useful for more than the ref attribute. It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes.
This works because useRef() creates a plain JavaScript object. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render.
Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.
https://reactjs.org/docs/hooks-reference.html#useref

Is it ok to pass class component reference to child component in react

class Parent extends React.Component {
handler = (event) => {
this.setState(state => ({ count: state.count + 1 }));
}
render() {
return (
<div>
{this.state.count}
<Child Parent={this} />
</div>
);
}
}
function Child(props) {
return <button onClick={props.Parent.handler}>increment count</button>
}
I have used this type of pattern a few times, didn't find any consequence, does anyone see any harm following such a pattern?
sometimes there are so many properties to be sent
In my opinion, if Child use almost all properties in Parent, maybe:
Child is Parent ?
split Child to multi Child like Child1、Child2 ?
And, if you pass Parent to Child, it's not semantic. I cannot aware what properties that Child needed when I use it elsewhere.
Looking forward to more discussion. :)
I am adding some benefits we get with this pattern, and I assume with my limited knowledge that this is ok
we can access props and state of Parent directly in child
can change parent state from child, using Parent.setState
can access other functions defined on the Parent class and thus reduce passing down everything as props
I feel this is a much better solution, because Parent reference never changes and therefore, it does not cause unnecessary rerender of child, and we do not need to memorize Parent' function references that we pass to child
While an argument of code smell may be raised by OO Specialist, that we are allowing child to modify properties of parent, we can safely ignore it for React, since we are anyway passing whole redux store to every component and any change in redux store, impacts so many components simultaneously.
---- following is an except from same question i posted on freecodeCamp. ------
Regarding code smell, only because one class is modifying other class’s properties. We have to think twice.
the whole concept of state is there so that it can be modified internally,
whether a class itself modifies or it gives right to some child to modify – it’s kind of similar thing, it’s only delegation that is the addition
Always to note, that the parent has full control over child. if child is not acting as per parent, the child can be replaced by parent.
To add one more point, we are anyways giving every component the right to modify whole redux store by useDispatch, thus argument of code smell doesn’t hold so strong for React per se
https://forum.freecodecamp.org/t/is-it-ok-to-pass-class-component-reference-to-child-component-in-react/408341/7

How does React's functional setState determine which fields have been updated?

From my experimentation, if you have an object as react state (let [state, setState] = useState({})), and you do something like
setState(s => {
s.a = 42;
return s;
})
It will not re-render components that depend on s.a.
If on the other hand you do
setState(s => {...s, a: 42});
It will re-render all components that depend on any field of s.
So it seems to me like it really only looks at whether the returned object reference of the closure is the same as the state it already has or not and makes a binary choice whether to re-render everything or nothing.
Is that correct?
Is there any way to update state in a way that makes it only re-render things that depend on e.g. s.a?
CONTEXT, if it helps: I need this for my application because performance is becoming impractical. My application retrieves JSON information from and API endpoint, which contains a list of 'fields' that describe input fields that the user can use to input data. When the user is done, the application submits this data in a single json. So all input components are controlled, through a single functional state that holds one property per field (I need to be able to programmatically update some fields sometimes). Performance is prohibitive because all fields (quite many now) are updated/re-rendered every time the user types a character in one of them. I sadly cannot create a new state for each field because the amount of fields is not known in advance.
As a note before I begin, this is not okay, and does not work in general. Treat all React state/props as immutable, otherwise you'll have issues.
setState(s => {
s.a = 42;
return s;
})
There is no way to selectively re-render your component, the reason why that mutation on setState doesn't re-render children that depend on s.a is because your component doesn't re-render at all when you update like this because the reference of s doesn't change, so react doesn't see that there's a change.
The only way to make children not re-render when parents re-render is to use React.memo, PureComponent, or shouldComponentUpdate. And those have to be applied to the children rather than the parent.
When does React re-render child component?

React Native receving new props, componentWillReceiveProps

I'm struggling with some updates on my Component. I know I shouldn't set props inside the states. However, I had to do this to make my component update properly:
componentWillReceiveProps(nextProps) {
this.setState({
doctor: nextProps.data.name,
address: nextProps.data.address
})
}
Is there a better way to do that? Is a best approach if I do this ->
componentWillReceiveProps(nextProps) {
this.props.data.name = nextProps.data.name;
this.props.data.name = nextProps.data.address;
})
}
I was trying to use the shouldComponentUpdate:
shouldComponentUpdate: function(nextProps, nextState) {
return nextProps.id !== this.props.id;
}
but I didn't work quite well for me.c
In your comment, you mention:
when I come back to the ListView the item I unfavourited still there
and another item disappeared
This looks like a problem in a completely different area. My guess would be that you are using the wrong key in a list. Probably an index. Keys should always be unique to the item you are displaying, and index is not (e.g. the first item is always index 0, and when you rearrange the list, or delete the first item, another item will have index 0, and react does not work well then.) Further explanation here.
About "updating the component properly":
If you pass in new props, react automatically re-renders with the new props. You do not need to do anything in componentWillReceiveProps for this.
componentWillReceiveProps is for updating state, based on comparing OLD and NEW props. (e.g. if you want to display whether number of likes in a prop has gone up or down)
shouldComponentUpdate is optional. Main purpose is to increase performance without any functional change to the workings of your component: to tell react early on that the component is unchanged. I would advise not to include shouldComponentUpdate as long as your component does not yet work as intended.
A wild guess here. As I perceive it, you experience issues properly implementing shouldComponentUpdate. I believe you try comparing nextProps.data objects and always have not equal result, even though the data within is equal. The reason for it is that the object references to data objects are different. In order to overcome that issue, you should be doing a deep comparison, similar to lodash's _.isEqual instead.
As mentioned in comments, updating nextProps in componentWillReceiveProps is a horrendous idea.

Categories