Different ways of destructuring props in react - reactjs

I have seen two ways to destructure props in React.
function MyComponent({name,age,height}){
// do stuff here
}
or
function MyComponent(props){
const {name,age,height} = props
// do stuff here
}
Suppose this component is used as
<MyComponent name="bob" age={25} height = {175} haspets={false}/>
Here is my questions:
If I used the first way of destructuring, does it mean that I will have no access to other pros, in this case haspets
What are some pros/cons of these two ways?

You can have access on the other properties of your object later, throught the arguments object, though as also pointed out on the link the rest parameters should be prefered.
<MyComponent name="bob" age={25} height = {175} surname="test" haspets={false} />
function MyComponent({ name, age, height, ...rest }){
// rest will be an object like { surname: 'test', haspets: false }
}
One of the differences I can think of, and I suppose the most important, is that on the second case, while you are destructing your props object, you are using const on declaration.
In that way, you can no longer change these values on your MyComponent, while on your first case you could easily modify them.

If you destructure your props from the function parameters, you won't be able to access any other props later on**, so your assumption is correct. As far as performance and other pros/cons though, these forms are pretty much identical. I happen to like this way, because I like as few additional variable declarations in my files as possible. It can, be a pain with functions that require lots of props.
**Unless you use the spread operator and store them in a separate variable.

Related

Why is using React Context better than just passing around a props object?

I've been reading about the advantages of using Context in React and I am unconvinced. I'm wondering if there's something I've missed.
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
What's the hassle in creating a props object in the main component and just passing it around among the underlings? Something like:
// do this once at top level (I'm assuming [foo, foo_set] and [bar, bar_set] are state variables):
const props = {foo, foo_set, bar, bar_set, thisAndThat, theOther, whatever, etcAndEtc}
// including one component
<MyComponent1 {...props } />
// including another
<MyComponent2 {...props } />
(Maybe better to use another name than props for this object, as the components can have other properties. Anyway.)
Then in MyComponent1 you can access all the props you want, or not access them. Either:
...
const MyComponent1 = (props) => {
...
// here we can use any props we need, props.bar, props.bar_set, props.theOther for example
const localVar = props.bar * 2;
props.bar_set(localVar);
// this changes the value of bar throughout the app
...
}
the advantage of the above, as I see it, is that you can pass around the props object to other sub-sub-components and not worry about whether you have anything missing.
Or:
...
const MyComponent1 = ({bar, bar_set, theOther }) => {
...
// here we can use bar, bar_set, theOther in the same example
const localVar = bar * 2;
bar_set(localVar);
...
}
The advantage of this option being that the syntax is shorter.
So my point is why not just use the standard JavaScript syntax? Why introduce new concepts when there are plenty to assimilate to do all sorts of other things?
Consider a fairly common case for most applications: You have authentication information (eg, the current user), a routing library (eg, react-router), and a theme object (what colors to use). These are needed in components scattered throughout the app.
You want to render a button somewhere down at the tip of the component tree. It's going to show the user's avatar, so it needs the authentication data. It's going to navigate when clicked, so it needs the navigate function from the routing library. And it needs to style itself according to the theme.
This certainly can be done through props, but in order for the button to get the props, every component in the chain above it must get and forward those props too. This could be many components deep, like page component -> section component -> table -> row -> widget -> button, and most of them don't need that information for themselves, so they're just taking the props in order to forward it along.
And you can easily imagine cases where there are more than 3 pieces of data that are needed across the app.
What's the hassle
Most people find this "prop drilling" to be a hassle, but let's assume you don't. You still have the problem that it has bad performance. If every component must receive the full set of "global" values that the app might need, then any time anything changes, the entire app must rerender. Optimizations like react.memo become effectively useless. You will get much better performance if you only pass the props you need.
Easier to edit code (You don't have to delete for example unused variable)
Better redability (You dont see unnescesary variables, and You see which component is using variables)
Lesser performance waste (preventing from consuming unnescesarry variables)
Suppose You got 10 descendants in - You would have to pass one variable through 10 of components.
What if some could have the same variable name ? You would have to edit Your passed variable for a while, then edit back later.
To sum up:
Using Context more efficient than stuffing everything into a single object variable, because it avoids re-rendering the whole app when anything changes.
People think passing a single variable around is more hassle than introducing specific syntax.
Context also allows you to have different values for the same variable in different parts of the app. This is shown here (the best explanation IMHO) : https://beta.reactjs.org/learn/passing-data-deeply-with-context
The above article also specifies that sometimes passing props is the best solution. It gives a list of use cases for context, and the advantages provided in each case.

Are parameters needed for inner functions to access props + variables of a React Functional Components

I have a functional component that has a couple of functions inside of it. In the example below, the inner functions are function1 and function2. I am trying to figure out if i need to explicitly pass the functional component's props (prop1, prop2), as well as other declared variables within the functional component (variable1, variable2) into these inner functions. Here is an example:
import React from 'react'
import * as d3 from 'd3';
function MyFunction({prop1, prop2}) {
const variable1 = '#333333';
const variable2 = 'Jimmy';
const function1 = () => {
d3.select('g.g1')
.append('rect')
.attr('color', variable1)
}
const function2 = () => {
d3.select('g.g2')
.append('text')
.text(prop1.label)
}
return (
<svg>
<g className='g1' />
<g className='g2' />
</svg>
);
}
export default MyFunction;
It seems to simplify my code if I don't have to explicitly declare parameters for function1 and function2 to be able to use these props + other variables declared in the upper scope, however I am not sure if this is a bad practice, or if this will cause other issues with my code. Is this okay?
Edit
Wanted to note that this does, in fact, seem to work without any issues. My question is more a matter of - should I do this / is it okay / are there problems I may run into down the road doing this?
Using a function in a function is perfectly fine. There are all kinds of articles you can read on if you should use useCallback. I'll talk about that in a second.
No, you don't need to pass the props to each function. The reason for this is closures and what it captures. Here is some reading on it under closures. Your arrow function closes over the props variable if they reference it. So nope, you don't need to pass it, and check out that link. And Chapter 2 if you really want to dig in depth.
As for performance, it's normally fine! Every time your component renders though, function1 and function2 will be redefined. They'll be the same exact function (unless d3 changes), but with a different reference, so the old function1 !== the new function1 even if they do the same thing. This is why that matters...
For a little more overhead though (per render of the component, possibly saving many renders of other components or useEffect executions), you can have react analyze if it should redefine function1 or function2 and if not, it keeps the same reference. This is what useCallback does. Honestly, I use useCallback if I'm ever unsure if the function will cause me issues. An example is when a child component has function1 passed in as a prop. That prop will ALWAYS be evaluated as a new value on every render of the parent because it's a new reference, unless you use useCallback.
You do want to pass the props as explicit arguments. As long as you don't pass any props that you're not using (prop2 above, for example), your code will not be simpler from omitting them. Especially as your use cases for them grows, along with the functions that need them, this will actually prevent verbose code.
But, as you found yourself, it is not required for a working component. The react docs show this throughout all of their examples. For ex - visit this link.
first of all this approach of having function inside a function is not recommended , it proves performance expenseive very often and yes if you have to use you need to pass the props into them. Also see this link here

Why create constants from props and state in react?

I see this code pattern a lot in React code:
render() {
const units = this.props.units;
const temperature = this.state.temperature;
return (<p>{temperature} {units}</p>);
}
and some developers I've asked say that its standard practice to pull state/props into local constants before using them in render or other functions - however, I can't find this practice discussed anywhere in the React docs, and the example code in those docs sometimes just access state/prop attributes directly.
I would prefer to use direct access because it makes the code more readable when you can immediately see where attributes are coming from instead of having to hunt down the local constant definitions.
Before I make this decision though, I was wondering if anyone knew why this practice exists and if there are good reasons to use it?
Is there a functional difference between the example above and this?
render() {
return (<p>{this.state.temperature} {this.props.units}</p>);
}
Its a standard practice to pull state/props when there a MANY props/state that are going to be used inside your functions
eg: const { prop1, prop2, prop3, prop4, ... } = this.props
const { state1, state2, state3, ... } = this.state
You can now reference them with the const names instead of
this.props.propName/stateName everywhere.
You shouldn't do that in the example you provided where there is just 1/few props/state
const units = this.props.units; // Not recommended
Bottomline : Just cleaner code. Matter of preference.
The reason why we need to get constants from props is to destructure the props object. Destructuring means your getting a property of the props object. With that you can lessen the code needed instead of using this.props.yourProps when you destructure it. It wil only be yourProps instead.
Also your destructure should be on es6 for es6 standards: Use
const {units} = this.props; //This gets the key units from the props object (es6 Syntax)
Instead of
const units = this.props.units; // This does the same but without using the es6 syntax
If you Structure your code in this manner you can write less code and can maintain it better... When we follow standards like this we won't worry even the organization switches from one developer to another.

Passing more parameters to a pure render function in React

Lately I've been trying to write my React components as "Pure Functions" and I've noticed that sometimes I want to have something which feels a lot like state. I was thinking about passing my state as a second parameter to my component. I can achieve this by calling my component as a normal function with two parameters, props and state.
For example:
// abstracted to it's own module
const useState = (Component, state = {}) => {
return class extends React.Component {
state = createState(this, state); // will traverse and update the state
render() {
const { props, state } = this;
return Component(props, state); // <-- call the Component directly
}
};
};
const Component = (props, { index, increase }) => (
<div onClick={increase} {...props}>
Click me to increase: {index}
</div>
);
const componentState = {
index: 0,
increase: (event, state) => ({ ...state, index: state.index + 1 })
};
const StatefullComponent = useState(Component, componentState);
<StatefullComponent style={{ color: "purple" }} />;
I have a CodeSandbox example:
My questions are:
Will this pattern harm performance?
I'm no longer extending the props with state values, this might be a good thing
I am messing with the way components are rendered by default, this might be a bad thing
Will this Pattern break things like shouldComponentUpdate? (I have a sinking feeling this is modelling the old context api)
How worried should I be that future react updates will break this code?
Is there a more "Reacty" way of using State in a Pure function without resorting to libraries like Redux?
Am I trying to solve something which should not be solved?
Note: I'm using state in this example, but it could also be a theme, authorisation rules or other things you might want passed into your component.
EDIT 19-03-2018: I have noticed that people seem to be confused about what I'm asking. I'm not looking for a new framework or a conversation about "why do you want to separate your concerns?". I am quite sure this pattern will clean up my code and make it more testable and "cleaner" in general. I really want to know if the React framework will in any way hinder this pattern.
At first glanced when I checked your code I had a question:
"Why do you make it so complicated? When you can simply make it with a class declaration".
But later when I have splitted your code I found it really worth to do that.
Question 1: Doesn't really make a difference, it is the way how HOC does the composition.
I'm no longer extending the props with state values, this might be a good thing
Why/When might it be a good thing?
I am messing with the way components are rendered by default, this might be a bad thing
I don't see that you break or mess the rendering by default, I think the HOC pattern promotes the same philosophy, the difference you separate state from props.
Question 2: If a developer decide to use a stateless component then he/she should realize all “lifecycle methods” or references ref will be not available.
Your pattern make stateless component as “statefull” but in stateless declaration - amazing 😋.
Like in JSX you write in JS an "HTML" and inside it JS code with another "HTML":
<ul>
{list.map(text => <li>text</li>)} // I know there should be used key
</ul>
Mr. Baudin pattern (state-full like stateless):
import React from 'react'
import {useState} from './lib'
const state = {
index: 0,
increase: (event, state) => ({index: state.index + 1})
}
const Component = (props, state) => (
<div onClick={state.increase} {...props}>
Click me to increase: {state.index}
</div>
)
export default useState(Component, state)
Question 3: It depends what break changes will be in coming versions.
Question 4: Well... I don't think the offered pattern (implemented library) can be considered as application state management but it can be used within any state management like Redux or Mobx because it deals with internal component state.
Question 5: No, I don't think. Your solution makes code less and clean. Functional components are good for very simple or representational components and now it can be extended with state.
While this question has been open I've done some painful research on the subject and I'd like to share this research with you.
Question 1: Performance; Calling your components as functions or even as constructor functions doesn't really make a difference. You simply get your component instead of a type.
// the component
const MyComponent = () => (<div>This is my page</div>);
console.log(MyComponent());
console.log(new MyComponent());
console.log(<MyComponent />);
console.log(React.createElement(MyComponent));
Pen (Don't forget to inspect the developer tools!)
What I've noticed is that when you call a component directly you lose a little information, for example, when I use JSX the type information is preserved:
React.createElement(MyComponent).type === MyComponent // <- true
MyComponent() // <- Now way to find out what constructed this...
This doesn't seem like a big deal because the MyComponent() is seen as a normal div so it should render correctly; but I can imagine that React might do some lookup on the type of the component and calling your function like this that might interfere with the performance.
Haven't found anything in the documentation nor in the source code to suggest that this is the case, so I see no reason to worry about performance at this point.
Question 2: Does this break shouldComponentUpdate; the answer is "maybe not", but not because I need to write a class as was suggested. The problem is that React does a shallow compare on the props when you use a PureComponent and with pure functions just expects that with the same props you get the same result. In my case, because of the second parameter it might think the component doesn't need to update but actually it should. Because of some magic in my implementation this seems to work for child components of a root component wrapped with the useState function.
This is as I expected the same problem as with the original implementation of the context api. And as such I should be able to solve it using some reactive techniques.
Question 3: Seeing how "just calling a component as a function" seems to be the entire idea behind react and seeing how it results in almost exactly the same component without the original type information I see no reason why this should break in the future.
Question 4/5: No, there is no more "Reacty" way of really solving this problem. There is how ever a more functional way. I could use a state monad and lift the entire thing up; but that would envolve a lot of work and I really can't see the benefit of doing that. Passing state as a second parameter seems, at least for now, as something which might be strange but viable and actually feasable.
Question 5: When I started looking around I didn't find a lot os answers to these questions, but now that I've really dug myself in I can see a few other libraries doing the same thing. For example: recompose which calls itself "lodash for react". They seem to use this pattern of wrapping your component in a function and returning a class a lot. (Their withState implementation).
Extra information: My conclusion is that this pattern (because it's nothing more than a pattern) is valid and does not break any fundamental rules of React. Just to give a little bit of extra information Bernardo Ferreira Bastos Braga wrote that I needed to use a class to do it "the React way". I fail to see how wrapping your function and returning a class with state is anything other than "using a class".
I do however realise that wrapping a function increases complexity, but not by much; function calls are really optimised and because you write for maintainability and optimise later.
One of my biggest fears is that when the software gets more and more complocated and we get more cross-cutting concerns to deal with, it will get harder and harder to handle every concern as a parameter. In this case it might be good to use a destructuring pattern to get the concerns which you need from a "concerns" obejct passed as the second parameter.
One last thing about this pattern. I've done a small test (Just selenium rendering a page a 100 times) and this pattern, on a small scale, is faster than using Redux. The bigger your redux state gets and the more components you connect the faster this pattern becomes. The down side is that you are now doing a bit of manual state management, this comes with a real cost in complexity. Just remember to weigh all options.
A few examples of why this state component
Applications which interact with users, require that you try to keep track of the interactions they have. These interactions can be modeled in different ways but I really like a stateful approach. This means that you 'thread' state through your application. Now in react you have a few ways of creating components. The three I want o mention are:
create a class and extend from Component
create a class and extend from PureComponent
create a stateless function
I really like the last option but, to be honest, it's a pain keeping your code performant. There are a lot of articles our there explaining how lambda expression will create a new function every time your component is called, breaking the shallow compare of the props done by PureComponent.
To counteract this I use a pattern where I wrap my stateless component in a HoC where I pass my component and my state object. This HoC does some magic and passes the state as a second parameter to the stateless function, ensuring that when the props are tested by the compare of the PureComponent it should work.
Now to make the wrapper even better I memoize the lambdas so that only a single reference to that function exists so that even if you were to test the function by reference it should still be OK.
The code I use for this is:
return Object.entries(_state).reduce(
(acc, entry) => {
const [key, value] = entry;
if (value instanceof Function) {
acc[key] = _.memoize(item => (...args) => {
const newState = value.apply(null, [...args, root.state, root.props]);
root.setState(newState);
});
} else {
acc[key] = value;
}
return acc;
},
{}
);
};
As you can see I memoize the function and call it proxying the arguments and passing in the state and the props. This works as long as you can call these functions with a unique object like so:
const MyComponent = useState((props, { items, setTitle }) => {
return (
<div>
{items.map(item => (
<Component key={item.id} item={item} changeItem={setTitle(item)} />
))}
</div>
);
}, state);
1- Will this pattern harm performance?
Performance is usually not a black/white, rather it is better / worse in different scenarios. Since React already has a standard way of doing this, it it plausible that you'll be missing out on internal optimizations.
2-Will this Pattern break things like shouldComponentUpdate? (I have a sinking feeling this is modelling the old context api)
Yes, you should be using the class declaration if you need to write shouldComponentUpdate functions
3- How worried should I be that future react updates will break this code?
I think is fair to say that you should, since there are obvious and documented ways of doing the same using classes.
4 - Is there a more "Reacty" way of using State in a Pure function without resorting to libraries like Redux?
you could have a container component that has state and pass down callback functions to update the state
5- Am I trying to solve something which should not be solved?
yes, since there is already a mainstream and documented way of archieving what you need using the Component class. You should probably resort to functional components only for very simple or presentational components

React: Why are props not frozen?

React suggests not to mutate props. I was operating under the impression that when props are passed in, they would be immutable or frozen.
The code below does not throw any errors and mutates the prop. Is this a bug?
try{
var a = this.props.a;
a.push('one')
a.push('two')
a.push('three')
console.log(a)
}catch(err){
console.log(err)
}
I'm not sure of the exact reasoning behind it or if that's documented somewhere but I could take a guess:
Freezing any assignment to a variable is not easy or even necessarily possible outside of using new-ish or even as of yet unimplemented browser features. Also deep freezing all your props in your app could have performance implications and would certainly need to be removed for prod builds.
Can you freeze assignment of a primitive variable? I don't think so. I think babel does it with const by statically checking code at compile time.
And can you freeze objects without Object.freeze or ES7's proxy? Again I don't think so, the es5-shim readme says:
which you cannot possibly obtain in legacy engines
What if someone does mutate something? These props are shallow copied, meaning you won't affect the parent prop unless you modify a nested object. However even if you did it would't affect the app, as that would get wiped out on the next render (just like your modifications).
If I got something wrong please let me know! This is just my reasoning.
It won't throw any error unless you frozen the object(props) explicitly.
Props are received from parents and immutable as far as the Component receiving them is concerned.
i.e React by default the props are immutable in the sense it is the concern of your component to maintain them as data received from parent and use as it is. Where as we can use state to maintain the local(component level data) that can be changed any time and keeping props contract with the parent.
Seems like this is the same behavior as const has, you can't reassign the value, but you can still push to the array or add keys to an object because those are not protected. Anyway, despite the possibility to do those mutations, you should not do this.
this.props.a = [1,2,3]; won't work
this.props.a.push(123); will work.
this.props.a = {name: 'John Doe'} won't work
this.props.a.name = 'John Doe' will work
If you try to reassign a prop in your component a type error will occur.
Uncaught TypeError: Cannot assign to read only property a ...
This is not true. Props are mutable by default. If you're using ES2015 you can make them read-only within your function be doing the following:
const { a } = this.props; // would create a const variable 'a'.
Same as:
const a = this.props.a;
While you won't be able to reassign 'a' now, you can still mutate it. Meaning, a = 'foo'; will throw an error, but you will still be able to do a.push('foo');.
If you want to use immutable data structures, try working with https://github.com/kolodny/immutability-helper or https://facebook.github.io/immutable-js/

Resources