Specifying variable outside of render in React class - javascript

import React from 'react';
import ReactDOM from 'react-dom';
class Parent extends React.Component {
let name=this.props.name;
render() {
return (
<h1>
{name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);e
Hi All,I'm new to React and i'm stuck in a problem,i wanted to display the name through props but its not working, if i use name=this.props.name inside render() it works fine,But how to get its value outside render,Please help out and Thanks in advance

According to the ES wiki
There is (intentionally) no direct declarative way to define either
prototype data properties (other than methods) class properties, or
instance property
Class properties and prototype data properties need be created outside
the declaration.
Properties specified in a class definition are assigned the same
attributes as if they appeared in an object literal.
a class definition defines prototype methods - defining variables on the prototype is generally not something you do.
To get the value outside of render, you can have a variable in the constructor and then access its value like
class Parent extends React.Component {
constructor(props) {
super(props);
this.name = props.name
}
render() {
return (
<h1>
{this.name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
With the Es7 initializers. you can do
class Parent extends React.Component {
name = this.props.name
render() {
return (
<h1>
{this.name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
However, since you are assigning a value based on the props, the ideal method is to make use of lifecycle functions and then use it. If you want to update in a state, then the better palce is to have this logic in the componentWillMount and the componentWillReceiveProps fucntion.
However if you only want to update the variable and use it in render, the best place is to have it in the render function itself
class Parent extends React.Component {
state = {
name: ''
}
componentWillMount() {
this.setState({name:this.props.name});
}
componentWillReceiveProps(nextProps) {
this.setState({name: this.props.name});
}
render() {
return (
<h1>
{this.state.name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
or
class Parent extends React.Component {
render() {
let name = this.props.name
return (
<h1>
{name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>

import React from 'react';
import ReactDOM from 'react-dom';
class Parent extends React.Component {
let name=props.name; // no need to use this.props.name
/* but a better way is to directly use {this.props.name}
inside the <h1> tag if you are not manipulating the data.
*/
render() {
return (
<h1>
{name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);

Related

Lifting State Up And Functional Components

I'm having trouble with lifting state up and converting components to functions. What's wrong with my code.
Instructions: 1: Inside the JS section, create a class component named App. Inside its render() method, have it return the Welcome component. In the ReactDOM.render() method, change Welcome to App.
2: Lift the state from the Welcome component to App, so that the state is initialized inside of App's constructor.
3: Convert the Welcome component to a function component that returns the same welcome message as before. You will need to pass the bootcampName property of state from App to the Welcome component. It's up to you whether or not to destructure it.
class App extends Component {
constructor(props) {
super(props);
this.state = {
bootcampName: "Nucamp"
};
}
render() {
return (
<div className="App">
<Welcome {this.state.bootcampName}>;
</div>
);
};
}
function Welcome(props) {
return (
<h1>Welcome to {this.props.bootcampName}!</h1>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
You have some errors there
You need to close the Welcome Component.
You need to name the prop
Destruct the props in because of this.state do not exist there.
Here the Code:
class App extends Component {
constructor(props) {
super(props);
this.state = {
bootcampName: "Nucamp"
};
}
render() {
return (
<div className="App">
{ /**
* you need to close the Welcome Component
* you need to name the prop
*/}
<Welcome bootcampName={this.state.bootcampName}/>;
</div>
);
};
}
// Here destruct props to use it
function Welcome({bootcampName}) {
return (
<h1>Welcome to {bootcampName}!</h1>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
Name the prop:
<div className="App">
<Welcome bootcampName={this.state.bootcampName} />
</div>
When you use functional components, you no longer need to use this. Try doing this instead:
class App extends Component {
constructor(props) {
super(props);
this.state = {
bootcampName: "Nucamp"
};
}
render() {
return (
<div className="App">
<Welcome bootcampName={this.state.bootcampName}>;
</div>
);
}
}
function Welcome({bootcampName}) {
return (
<h1>Welcome to {bootcampName}!</h1>
);
}

difference between onClick={() => this.func()} and onClick={this.func} in React js [duplicate]

I want to know the difference between these two statements in react.
<Button onClick={this.Callme}></Button>
<Button onClick={()=>this.Callme()}></Button>
Its just syntax or is there any difference in functionality too.Thanks
If the function depends on having a calling context of the instance, and the function isn't bound to the current instance already, the first code won't work, because the this inside callMe will be undefined:
class Component extends React.Component {
name = 'component_name';
Callme() {
console.log(this.name);
}
render() {
return (
<button onClick={this.Callme}>Click</button>
);
}
}
// Render it
ReactDOM.render(
<Component />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
The second code works, because the this in the anonymous arrow function will inherit the this from the outer scope, the instance:
class Component extends React.Component {
name = 'component_name';
Callme() {
console.log(this.name);
}
render() {
return (
<button onClick={() => this.Callme()}>Click</button>
);
}
}
// Render it
ReactDOM.render(
<Component />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
If the Callme method does not need to refer to the instance, then either type of onClick works.
Other solutions to this common problem include:
Binding the method in the constructor (this.Callme = this.Callme.bind(this))
Binding the method when setting the callback (onClick={this.Callme.bind(this)}>)
Defining the method as an arrow function in the constructor (or as a class field), rather than as a property of the prototype
class Component extends React.Component {
this.Callme = () => {
console.log(this.name);
}

Is it possible to inject react context to div outside the root in react (under the body)

I am working with react cytoscape library. Try to integrate to popper plugin of cytoscape.
the popper "content" property expect to return a div element describe the popper which appended to the "body" element.
Since the context provider is under the root element , that div can't be consumer of that context.
How can I use the same context also in the popper element which define outside the root.
Working with react component for cytoscape but the plugins of cytoscape are in pure js.
<body>
<div id=root>
<Style_Provider>
.
.
.
</Style_Provider>
</div>
<div id="popper">
// need to access to style context
</div>
</body>
As Eric Hasselbring said, portals address this use case:
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
Here's an example, using context:
const ExampleContext = React.createContext(
"default context"
);
class Example extends React.Component {
render() {
return (
<ExampleContext.Provider value="context from Example">
<div>
This is the parent comnponent.
<MyPortal />
</div>
</ExampleContext.Provider>
);
}
}
class MyPortal extends React.Component {
static contextType = ExampleContext;
render() {
return ReactDOM.createPortal(
<div>This is "my portal," context stuff is "{this.context}"</div>,
document.getElementById("portal")
);
}
}
ReactDOM.render(
<Example />,
document.getElementById("root")
);
<div id="root"></div>
<hr>
<div id="portal"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
In a comment you said:
the popper creates those 'divs' dynamically. Hence, I cant create 'MyPortal' component initially.
Just make the creation of the portal conditional. Here's the above, but with a button to show/hide the portal:
const ExampleContext = React.createContext(
"default context"
);
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
showPortal: false
};
this.showHideClick = this.showHideClick.bind(this);
}
showHideClick() {
this.setState(({showPortal}) => ({showPortal: !showPortal}));
}
render() {
const {showPortal} = this.state;
return (
<ExampleContext.Provider value="context from Example">
<div>
This is the parent comnponent.
<input type="button" value={showPortal ? "Hide" : "Show"} onClick={this.showHideClick}/>
{showPortal && <MyPortal />}
</div>
</ExampleContext.Provider>
);
}
}
class MyPortal extends React.Component {
static contextType = ExampleContext;
render() {
return ReactDOM.createPortal(
<div>This is "my portal," context stuff is "{this.context}"</div>,
document.getElementById("portal")
);
}
}
ReactDOM.render(
<Example />,
document.getElementById("root")
);
<div id="root"></div>
<hr>
<div id="portal"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Defining React Prop Keys When Calling Static Child Components

I'm trying to better understand the role of keys in React components. I've read quite a bit but every example I've seen (like the one in the React docs or the great explanation on S.O.) assumes the data coming into the component is dynamic.
The examples all apply keys with array index values or using something like .map() to assign database IDs dynamically to each instance of the child component, and satisfy React's need for keys.
My example is on a static site with static content coming into the child component that gets called a couple of times. Best I figured, I could create a random number generator function getRandomInt and apply the key that way.
Unfortunately this results in the familiar React error:
Each child in an array or iterator should have a unique "key" prop.
Check the render method of CaseStudyOpinionSummary. It was passed a
child from DiagnosticCaseStudy.
Where am I going wrong?
Parent component (DiagnosticCaseStudy)
import React from 'react'
import CaseStudyOpinionSummary from '../../../components/CaseStudyOpinionSummary'
export default class DiagnosticCaseStudy extends React.Component {
getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
render() {
return (
<CaseStudyOpinionSummary
part="Part One"
partTitle="Diagnosis"
partSubtitle="Primary Care Encounter"
partSummary="Short brief"
key={ this.getRandomInt(0, 100000) }
/>
<CaseStudyOpinionSummary
part="Part Two"
partTitle="Medication and Management"
partSubtitle="Initial Gastroenterologist Encounter"
partSummary="Another short brief"
key={ this.getRandomInt(0, 100000) }
/>
)
}
Child component (CaseStudyOpinionSummary)
import React from 'react'
export default class CaseStudyOpinionSummary extends React.Component {
render() {
return (
<div>
<section className="lightest-gray-bg">
<section className="aga-cs-container-short">
<section className="aga-container">
<h2 className="aga-cs-orange-title">{[this.props.part, ": ", this.props.partTitle ]}</h2>
<h2 className="aga-cs-question-title">{ this.props.partSubtitle }</h2>
{ this.props.partSummary }
</section>
</section>
</section>
</div>
)
}
}
React only needs the key prop to distinguish between sibling components in an array. You don't need the key prop for regular sibling components.
class AppWithArray extends React.Component {
render() {
return (
<div>
{[
<div key="1"> test1 </div>,
<div key="2"> test2 </div>
]}
</div>
);
}
}
class AppWithoutArray extends React.Component {
render() {
return (
<div>
<div> test3 </div>
<div> test4 </div>
</div>
);
}
}
ReactDOM.render(
<div>
<AppWithArray />
<AppWithoutArray />
</div>,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
When a component gets a new key prop, the old one will be unmounted and thrown away and a new one will be created and mounted. You almost never use the key prop outside of arrays, but it can be a nice technique to keep in mind if you ever need to create an entirely new component.
class Timer extends React.Component {
timer = null;
state = { count: 0 };
componentDidMount() {
this.timer = setInterval(() => {
this.setState(prevState => ({ count: prevState.count + 1 }));
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
return <div>{this.state.count}</div>;
}
}
class App extends React.Component {
state = { timerKey: 1 };
componentDidMount() {
setTimeout(() => {
this.setState({ timerKey: 2 });
}, 5000);
}
render() {
return <Timer key={this.state.timerKey} />;
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Can class object be called from React Component Prop?

I'm studying ReactNative.Navigator.renderScene props.
'use strict';
import React,{Component} from 'react';
import ReactNative from 'react-native';
const {
TouchableHighlight,
Navigator,
AppRegistry,
Text,
View,
} = ReactNative;
class TestClass extends Component{
render(){
return <Text>test</Text>
}
}
class MyTag extends Component{
render(){
return <Text>test</Text>
}
}
class Main extends Component{
render(){
const routes =[{component:TestClass,index:0},{component:MyTag,index:1}]
return(
<Navigator
initialRoute={routes[0]}
initialRouteStack={routes}
renderScene={(route, navigator) =>
<View><TouchableHighlight onPress={() => {
if (route.index === 0) {
navigator.push(routes[1]);
} else {
navigator.pop();
}
}}><View>{route.component}</View>
</TouchableHighlight></View>
}
/>
)
}
}
AppRegistry.registerComponent('ChoiceComponent', () => Main);
Can component in routes variable be called by using {route.component} in renderScene props in JSX?
TestClass is called correctly if {route.component} is changed into <Test Class />.
You're asking if you can use an object property (route.component) in place of a class name. Absolutely! Remember, these are just identifiers. You use it exactly the same way you used the class name.
So instead of
{route.component}
you want
<route.component />
(But keep reading, we may have to do more.)
Example:
class Example1 extends React.Component {
render() {
return <div style={{color: "blue"}}>{this.props.text}</div>;
}
}
class Example2 extends React.Component {
render() {
return <div style={{color: "green"}}>{this.props.text}</div>;
}
}
const routes = [
{component: Example1},
{component: Example2}
];
ReactDOM.render(
<div>{routes.map(route => <route.component text="Hi there" />)}</div>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
The above works, but as far as I can tell from the React documentation, our component identifier name should start with a capital letter:
User-Defined Components Must Be Capitalized
When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like <Foo /> compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.
In our case, it's route.component, which is currently handled correctly (because of the .; it wouldn't if it were route_component, for instance), but that appears to be undocumented behavior. (Supporting the . is documented behavior, what appears undocumented is allowing you to start with a lower-case letter when it's not a simple identifier.)
So I think to be officially in line with the docs, we'd want to assign that to a capitalized identifier:
const RouteComponent = route.component;
return <RouteComponent text="Hi there" />;
Like so:
class Example1 extends React.Component {
render() {
return <div style={{color: "blue"}}>{this.props.text}</div>;
}
}
class Example2 extends React.Component {
render() {
return <div style={{color: "green"}}>{this.props.text}</div>;
}
}
const routes = [
{component: Example1},
{component: Example2}
];
ReactDOM.render(
<div>{routes.map(route => {
const RouteComponent = route.component;
return <RouteComponent text="Hi there" />;
})}</div>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Categories