React.js: Passing props to props? - javascript

I am learning React via an online course and have stumbled across a situation where a property is attached to another property like so:
this.props.property01(this.props.property02)
Seeing as the tutor only briefly addresses this line of code I cannot but remain baffled as to what this "concatenation" syntax actually stands for, i.e. what it causes behind the scenes. Coming from Vanilla JS it looks like property02 is being used as an argument for property01 but that seems too simple an answer. That being said, I understand the remaining code quite well.
To provide some context I have created this codepen in which the problem I refer to above is given by this.props.onDelete(this.props.whichItem);.
Seeing as I could not find any related questions, I would be grateful for some insightful elaboration on this one.

The properties of a React component can be functions. When I see:
this.props.property01(this.props.property02)
I think that:
this.props.property01 is a function.
this.props.property02 is passed to the function as an argument.
This means that the component would be used as:
<SomeComponent property01={(a) => { /* so something with "a" ... */ } property02={"someValue"} />
If property02 is only used to be passed to property01 and nothing else I would prefer something like:
<SomeComponent property01={(a) => { /* do something with "someValue" ... */ } />
Which means that there is no need for a property called poperty02.

Coming from Vanilla JS it looks like property02 is being used as an argument for property01
That's it, you are correct.
this.props.property01(this.props.property02)
property01 is a method, property02, the argument.
A more elaborated explanation for anyone else looking at this:
Assume this line is in a component called MyComponent and property01 is a prop in MyComponent.
The parent component's render() method, would contain something like this:
<MyComponent property01={this.someMethod.bind(this)} />
Where someMethod belongs to that parent component but it becomes available as property01 in MyComponent (the child component).

If you can understand the basic react code this question will help you because in that code I passed props and state from parent component to the child component. You can play with it try to do whatever you want.
How to pass state from parent compont to child component in route (react-route-dom) reactjs

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();

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).

How a component pass a prop to another component?

Newbie here, I am studying the documentation of react and in React Context API, I couldn't understand something, I won't understand the rest of the subject if I don't understand it. Can anyone help me what does it mean through using an example?
The Toolbar component must take an extra "theme" prop
and pass it to the ThemedButton. This can become painful
if every single button in the app needs to know the theme
because it would have to be passed through all components.
class App extends React.Component {
render() {
return <Toolbar theme="dark" />;
}
}
function Toolbar(props) {
// The Toolbar component must take an extra "theme" prop
// and pass it to the ThemedButton. This can become painful
// if every single button in the app needs to know the theme
// because it would have to be passed through all components.
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}
class ThemedButton extends React.Component {
render() {
return <Button theme={this.props.theme} />;
}
}
The Toolbar component must take an extra "theme" prop
this can be like <Toolbar theme="dark">
and pass it to the ThemedButton
how Toolbar component pass this prop to ThemedButton? and kindly clarify the rest of the comment as well.
Thank you for any help? You are kind
In your Toolbar component, it takes a parameter props, props is whatever properties have been passed to it when calling it, as in <Toolbar param1="someString" param2={someVariable}>, in this case the props value in Toolbar will be an object with the data you passed as key=value like for example: {param1: "someString", param2: content_of_someVariable}
And if you don't actually use those props (properties)/parameters in Toolbar, but rather in a subcomponent, then you have to pass them again to another level, like in <ThemedButton theme={props.theme} />, then ThemedButton itself finally passes the value to the component that actually makes use of, which is in your case: <Button theme={this.props.theme} />;.
So you had to pass the theme across multiple components, which don't use it or care at all about it, just to get it through to the final Button component.
(answer ends here, below is my effort to explain context API in an easy way)
To avoid that annoying level to level to another..., you can use the context API. Because it is really incontinent to pass a value across 3-4+ levels/components every time you want to use it in the last one in the chain.
Think about the context like a variable defined and exported on a root level and holds some data (like the user login status for example, or the theme infomation), and whenever you require that data, you import it and use it directly. You use the Provider property of the context you define (MyContext.Provider) to assign the data to it, and you use the Consumer property (MyContext.Consumer) to consume/access that data you assigned in the provider.
The beauty of the context consumer, is that whenever the data is updated in the provider, the consumer immediately gets the new data and triggers a re-render with the new data.
I hope I explained it in a simple and clear way. Write a comment with any questions or unclear parts and I can try my best to improve the answer.
Best of luck!
Props are properties that help define the way your JSX appears on the page.
When you use a component that you have created, you can pass it props like below:
<MyComponent myProp={myPropValue} />
You can continue to pass props down through the component hierarchy as well. So say you have a component tree like below:
MyComponent
--MySubComponent
----MySubSubComponent
You can pass props from MyComponent to MySubSubComponent like so:
<MyComponent myProps={MyProps} />
<MySubComponent mySubProps={props.myProps} /> //Props are the value you gave in the parent component
<MySubSubComponent mySubSubProps={props.mySubProps} />
Whatever title you give the props when declaring the component in JSX is the title you will call to get the value of the prop like props.myProps

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.

this.refs.something returns "undefined"

I have an element with a ref that is defined and ends up getting rendered into the page :
<div ref="russian" ...>
...
</div>
I want to access the DOM element properties like offset... or something. However, I keep getting undefined and I haven't the faintest idea why. After some searching it's clear that refs are only applicable to one file but I'm not using this anywhere besides this one page. I'm saying this to log it:
console.log('REFS', this.refs.russian);
What could be causing this?
Check that you are not accessing ref before the child component has been mounted. E.g. it doesn't work in componentWillMount. A different pattern which auto invokes ref related callback after the element has been mounted is this-
<div ref={(elem)=>(console.log(elem))}/>
You can use this notation to get mounted elements in deep nesting as well -
<div ref={this.props.onMounted}/>
The correct place to work with refs is inside specific React lifecycle methods e.g. ComponentDidMount, ComponentDidUpdate
You cannot reference refs from the render() method. Read more about the cautions of working with refs here.
If you move your console.log('REFS', this.refs.russian); call to ComponentDidMount or ComponentDidUpdate lifecycle methods (assuming you are on React >= 14) you should not get undefined as a result.
UPDATE: also refs will not work on stateless components per the caution link above
Update since React version 16.4
In your constructor method define your ref like this
constructor(props) {
super(props);
this.russian = React.createRef();
}
In your render where you are using ref do this.
<input
name="russian"
ref={this.russian} // Proper way to assign ref in react ver 16.4
/>
For e.g if you want to have focus when component mounts do this
componentDidMount() {
console.log(this.russian);
this.russian.current.focus();
}
Reference Refs Documentation React
I was having a similar issue in my form validation methods, trying to assign this.ref.current.reportValidity()
Writing the method I was doing this in as validate = () => {} instead of validate() {} helped me out, but I'm not totally sure why exactly, just something I remembered from habits I had in my past work experience that gave me this. Hope it helps and could someone kindly clarify this answer with why this might work exactly.
If you are exporting class withStyle, please remove and export default nomally.
Instead of putting your Console.log inside the function example(){...} you should put it inside:
example=()=>{....}

Categories