is it ok to define a function inside a React stateless component? - javascript

Is it bad practice to define a function (like handleClick in the example below) inside a stateless component? I was told that you should avoid doing so, but I can't find anything in the documentation to confirm it. If the answer is "yes" then why is defining a function into a class instead any better?
function MiniPalette(props) {
const {classes } = props;
function handleClick() {
history.push(`palette/${id}`);
}
return (
<div className={classes.root} onClick={handleClick}>
<div className={classes.colors}>{miniColorBoxes}</div>
<h5 className={classes.title}>
{paletteName}
<span className={classes.emoji}>{emoji}</span>
</h5>
</div>
);
}

It is generally a bad practice in javascript, not in React in particular. Basically if you declare a function inside a function, every time you call the parent function it will initialize the child function as well and it is a waste of resource. For details you can also check out this: https://code.tutsplus.com/tutorials/stop-nesting-functions-but-not-all-of-them--net-22315

Viet is correct in that it's a waste of resources. A good way to look at the component tree is that you want to process data at the top and near the bottom your focus is only in rendering the data. If for example you need a way to manipulate the data and update state, I would suggest passing hooks down or diverting to useContext(). This will also keep your code cleaner and you can eventually make use higher order components for like-functions.

Related

How to re-render index.js through a function in a different file. REACT

I've been working on react native for the last 3 months, but i have no experience when it comes to building a website in just react. I would like to know if its possible to re-render the "index.js" file, after a certain function in a different file is called? I want to know if maybe i can do this through a useState variable, lets say "firstTimeLoading", that only calls that function when its true and then that said function changes that variables state to false, so that way that function is only called once. Is it possible to use this method? Is it the best choice here? And how do i pass that varaible to another file so i can change its state?
Ooh thats a tricky one, i'm not that great at redux but i think redux could solve that problem. However some tricks i used which aren't great is by emitting functions that change the state in the parent. In that way does the parent rerender and the childrens rerenders aswell.
function changeName() {
setState({name: "test"});
}
render(){
return(
<Child emitter={this.changeName} />
)
}
this way does the child call changeName with the help of props and the parent later calls its function since the function "changeName" is in the props to the child.
if you want to update the whole site could you simply use this terrible call:
window.location.reload();

Thus returning a JSX necessarily makes the function a component?

I have simple code, I have a component called Feed with some props.
On the main content component called Articles I map through a js object and return Feed component
Now, everyone are using an anonymous function to do so.
<div>
{data.map(()=> <Feed/>))} (sorry if the syntax a bit wrong but you get the idea
</div>
now, I took the function that returns Feed outside the map function
function createFeed (feedData) {
return <Feed props/>
}
and put it
<div>
{data.map(createFeed)}
</div>
and it workds wonder, but, thus createFeed is also a component (so I need to change the name to CreateFeed) or is this just a function that return an object to a new array created by the map function thus it's only a function and not a component?
There's no magic here.
<div>{data.map(createFeed)}</div>
Is equivalent to:
<div>{ data.map(item => createFeed(item) }</div>
Since the createFeed function returns the component without adding any logic, you can just omit it and return the component. It's all the same.
Edit:
In your case, you're merely using the function as a factory, not as a functional component, so you could argue that it doesn't need to be capitalized.
That is, if you're sure that you won't use the function as a component in Jsx, this is not a problem. If you want to use it as Jsx, this causes a problem, which is documented here: https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized
If there is no use in having a factory function, I would omit it, but in the end choice is up to you.

React: Should I pass this reference of parent component to child component

I has received a requirement from my boss which is analyzing existing code of my colleagues. I encounter some of weird code like this:
class Parent extends React.Component {
methodA () { ... }
methodB () { ... }
render () {
<div>
...other lines of code
<Child parent={this} />
</div>
}
}
And inside of child component, they use this.props.parent.methodA() and other parent methods like so instead of passing function as props.
I am proposing a rule not to use that pattern. Because that's pretty unreadable and the behaviors of those functions might be sometime unpredictable.
I am wondering besides things which i am talking about, does this pattern could run into any performance issues?
Thanks in advance.
Most usual scenario is when child calls some method from parent on click event, for example.
In that case you pass just that method.
<Child doSomethingMethod={methodA} />
and then in Childs render method:
<button onClick={doSomethingMethod} />
I can’t think of an example where child should be aware of parents implementation.
In your case, parent should always have methodA and if you ever decide you want to change parent structure, you need to change child as well.
On the other hand, when you pass just a method, your child doesnt care where the parent got that method from. So, its loosely coupled where each component handles itself only and receives only those params from other component that it needs (including functions).

Is the reason props in React shouldn't be changed/mutated is because React wants elements to be as predictable as possible?

From React documentation.
Conceptually, components are like JavaScript functions. They accept
arbitrary inputs (called “props”) and return React elements describing
what should appear on the screen.
Considering:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
or
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Will give us the ability to do this:
<Welcome name="Luke" />;
<Welcome name="Leia" />;
to use as we wish in the DOM,
Hello, Luke
Hello, Leia
Now when people prescribe props shouldn't be changed, it would make sense the reason is in my thinking would be like the same as changing the values of attributes of an image tag?
HTML:
<img id="Executor" alt="Picture of Executor" src="/somepath/vaders-star-destroyer-executor.jpg"/>
JS:
Meanwhile in a Javascript file a long time ago in a galaxy far, far away...
var imageOfVadersStarDestroyer = document.getElementById('Executor');
imageOfVadersStarDestroyer.src = "/somepath/vaders-star-destroyer-avenger.jpg"
Because if we keeping changing an elements attribute values this can cause confusion and slower renderings?
So is the reason why the prescription is to never change props in React is because is the library is trying to make elements as predictable as possible?
Setting props outside of React is dangerous and should be avoided. Why? The main reason is that it doesn't trigger re-renders. Hence bugs and unexpected behaviour.
Re-rendering
Most of the time, props are data that is store as state in the parent component, which is manipulated by calling setState() (or the second function returned by React.useState()). Once setState() is called, React re-renders and computes what has changed under the hood, with the latest props and state. Manually assigning values to props, therefore won't notify React that the data has changed and something has to be re-rendered.
The good practice
Making props read-only allows React components to be as pure as possible, which is obviously a good practice anyway even when writing plain JS. Data won't be changed unexpectedly and can only be done so by calling setState() (You might have heard of the single source of truth, which is what React is trying to leverage).
Imagine you notice something went wrong in the app and the data shown to the end user is completely different from the source, it would be a pain trying to find out where the data has been manipulated wouldn't it? :)
never change props in React
means that you should never do this.props.name = "userName" because of React's one way data binding, props are read only, to update a component's props, you should pass a function from the parent that will do that ( in the parent ) , or dispatch an action if you're using redux, a change in the props will trigger a re-render
props is a constant in this case. You will always need it in your components.
But there is a cleaner way to write it or even omit it.
Regular way with Function Expression (same as your exemple)
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
ES6 Object Destructing - explicit
function Welcome(props) {
const {name} = pros
return <h1>Hello, {name}</h1>;
}
ES6 Object Destructing - inplicit, cleaner way
function Welcome({name}) {
return <h1>Hello, {name}</h1>;
}
And of course, you can use the class way which requires the usage of this.props.yourAttr
However, in the new version 3 of create-react-app, changed class components to functional components. You can see this exact modification on Github here.
You can need to learn more about destructing assignment in the old and good MDN linked here or an in-depth approach both array and object destructuring here.

Debugger inside React Context API Consumer block - this is undefined

I am trying to debug a component using Context API Consumer inside render method on browser dev tools. If i place break-point inside Consumer block, i can't print props etc. on console dynamically as this is undefined. Normally running this works fine, but while debugging only value of this is undefined. Following is sample render method of component.
componentMethod = () => {
console.log(this.props.name); //Placing breakpoint here, value is this is defined
}
render() {
return (
<div className={styles.container}>
<div>
<h4>{this.props.name}</h4>
</div>
<div className={styles.block}>
<MyComponent.Consumer>
{
({ firstParam, secondParam }) =>
<AotherComponent
firstParam={firstParam}
secondParam={secondParam}
thirdParam={this.props.name}
/>
}
</MyComponent.Consumer>
</div>
</div>
)
}
I could be related fat arrow use here, but I am able to get value of this while using break-point in componentMethod. Is there a way to bind this for Consumer block?
Try this, however, your question doesn't give enough context on what you are trying to solve. It would be better if you shared the Provider implementation as well and where you use it.
render() {
const { name } = this.props;
return (
<div className={styles.container}>
<div>
<h4>{name}</h4>
</div>
<div className={styles.block}>
<MyComponent.Consumer>
{
({ firstParam, secondParam }) =>
<AotherComponent
firstParam={firstParam}
secondParam={secondParam}
thirdParam={name}
/>
}
</MyComponent.Consumer>
</div>
</div>
)
}
It looks like you are interested in knowing what your consumer is passing down to your component during execution. There are two ways to accomplish it.
Hard Way
Let us breakdown how the consumer works (using your sample). That may help you with finding the right place to debug.
in your render() method, you have a <MyComponent.Consumer> call. The new Context Consumer API is built on the render-prop pattern.
Important thing to remember about the render-prop pattern is that: it is a function call. This function should return something which react can consider while rendering the tree.
Since it is a function call, you can put your console.log statements before your element. You will have to add an explicit return statement though.
As to why it is undefined in your method. I am assuming that the componentMethod is not a lifecycle method, so it is possible that this or this.propsis undefined based on how you are invoking that method. I do not see it invoked anywhere in your render method.
Eas(y/ier) Way:
Use react dev tools browser extension. You can look up all components by name. On clicking them you can see the props and state and even the context (as far as I remember). You can even change the values and see react react to it!

Categories