I am currently learning React and I do not understand when should I use these and when should I not? I have seen tutorials where people just use them seemingly interchangeably. Hence, I would like to know what is the differences between them and when should i or should i not use them.
For example, assuming the "function" named component returns a <div>Hello</div> after the call, I can have the following code.
import {function} from './component';
class X extends React.Component{
render(){
return(
<div>
<function Props1="Hello"/>
</div>
)
}
}
Next,I believe can also have the following code, please correct me if I'm wrong
import {function} from './component';
class X extends React.Component{
render(){
return(
<div>
{function("Hello")}
</div>
)
}
}
So it seems like there are two ways for doing the exact same thing in ReactJS? Are there any reasons I should be using one over the other?
When you render it like <function Props1="Hello"/>, React will create a props object, with the properties and values pairs you passed to it.
When you render it like {function("Hello") your props argument will be a string "Hello".
See snippet below:
function App() {
return(
<React.Fragment>
<Component1
props1="hello"
/>
{Component2("hello")}
</React.Fragment>
);
}
function Component1(props) {
return(
<React.Fragment>
Component1
<div>Props: {JSON.stringify(props)}</div>
<br/>
</React.Fragment>
);
}
function Component2(props) {
return(
<React.Fragment>
Component2
<div>Props: {JSON.stringify(props)}</div>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<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>
<div id="root"/>
The difference is that first case it is stateful component, so the props has to be passed by something like in your case
Props1=""
then in your function component which in this case is stateful ,you get access to props via this.props.Props1
in second case it is functional component so you can get access to it like for example:
class X extends React.Component{
render(){
return(
<div>
{function("Hello")}
</div>
)
}
}
function function(myprop) {
return <div>{myprop}</div>
}
Related
Is there a way using a High Order Component to add elements programatically to a Component? I was wondering if there was a way using React.createElement to append the component's children? Here is the code that I have so far:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
function addAnElement(WrappedComponent) {
return class Enhancer extends WrappedComponent {
render() {
const elementsTree = super.render()
// Programatically add a child?
// Update elementTree.props.children somehow?
return elementsTree
}
}
}
class JustSomeText extends Component {
render() {
return (
<div>
<p>A long time ago, in a galaxy far, far away.</p>
{/* I want to add an element here? */}
</div>
)
}
}
function App() {
const ExtendedComponent = addAnElement(JustSomeText)
return (
<div className="App">
<ExtendedComponent />
</div>
)
}
export default App
ReactDOM.render(<App />, document.getElementById('root'))
I'm also interested in other, more effective ways to achieving the same result.
The simplest way to achieve this (although it does not use HOC) is using the children prop in React.
class JustSomeText extends Component {
render() {
return (
<div>
<p>A long time ago, in a galaxy far, far away.</p>
{this.props.children}
</div>
)
}
}
function App() {
return (
<div className="App">
<JustSomeText>
<p>more text!</p>
</JustSomeText>
</div>
)
}
This will render the following:
<div className="App">
<div>
<p>A long time ago, in a galaxy far, far away.</p>
<p>more text!</p>
</div>
</div>
Refer to this for further detail on children - https://reactjs.org/docs/composition-vs-inheritance.html
Is it possible to use ReactDOM.createPortal inside <React.Fragment> with another element that is rendered to where the component is rendered or am I doing something wrong here?
class Component extends React.Component{
render(){
return (
<React.Fragment>
ReactDOM.createPortal(<h1>Hello</h1>,
document.getElementById('side'))
<h1>Hello</h1>
</React.Fragment>
);
}
}
Yes it is entirely possible, you just need to wrap React.createPortal within {} like
class Component extends React.Component{
render(){
return (
<React.Fragment>
{ReactDOM.createPortal(<h1>Hello</h1>,
document.getElementById('side'))}
<h1>Hello</h1>
</React.Fragment>
);
}
}
Working codesandbox
I have a simple react library who's props I want to manipulate. For that I encapsulated it in a HOC.
Example, This is the class from the library:
class Hello extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
My Simplified HOC:
const ReplaceHello = (props) => {
return <Hello name={props.world()} />
}
I am doing this to replace the "name" string field in the library with a function that does some kind of work and returns a string. Sample:-
ReactDOM.render(
<ReplaceHello world={function(){ return 5*3}} />,
document.getElementById('container')
);
The library however has another component, which uses the original 'Hello' component, like below:
class World extends React.Component {
render() {
return <div>
{this.props.data.map(function(value){
return
<Hello key={value.id} name={this.props.name} />});}
<p> Thus the story begins</p>
</div>;
}
}
However now I am at my wits end how to either encapsulate or manipulate the World class to replace <Hello> with <ReplaceHello>. As both 'Hello' and 'World' are a part of the library I cannot change that code and I want to generate the name field based on the result of a function.
I would like to replace the <Hello key={value.id} name={this.props.name} /> to give me the functionality <Hello key={value.id} name={value.name} />
It seems, I see two equal ways to delegate property via props:
let App = React.createClass({
render(){
return (
<Unit someName="Push me!" />
)
}
});
class Unit extends React.Component{
render(){
return (
<button>
<span className="glyphicon glyphicon-heart"/>
{this.props.someName}
</button>
)
}
};
and
let App = React.createClass({
render(){
return(
<Unit>
<span className="glyphicon glyphicon-heart"></span>
Push me now!
</Unit>
)
}
});
class Unit extends React.Component{
render(){
return (
<button>{this.props.children}</button>
)
}
};
What's the general purpose of props.children?
Can I consider it as equal to props.someName?
Could be provided some examples where props.someName doesn't work but props.childred does?
Maybe I am wrong, but I think that the existence of children is just syntactic sugar to allow an HTML-like nesting of elements. As far as I know, it is exactly the same as any other property. In fact, while using JSX you can add children as an ordinary property and it doesn't make any difference.
let App = React.createClass({
render(){
return(
<Unit children={<span className="glyphicon glyphicon-heart">Push me now!</span>}/>
)
}
});
class Unit extends React.Component{
render(){
return (
<button >{this.props.children}</button>
)
}
};
ReactDOM.render(<App/>, 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>
Generally speaking, this.props.children is used to refer to all the children that are wrapped in a custom component.
<View>
<Text>One</Text>
<Text>Two<Text>
</View>
Here, the two Text elements are children to your View. In the class definition(or equivalent) for your View component, you can refer to all the children components by this.props.children. But I think you already understand this much.
From what I understand, as a rule of thumb, you pass some values/properties, etc as props to a component.
If you want to, for example, render some components in a custom component that you are defining, you need to be able to refer to what components were declared in the implementation code from definition code, so you use this.props.children.
My language is a bit muddled, but I hope this is clear enough.
wonder if it is possible to pass a component a property as following
ReactDOM.render(
<ContainerBox anotherComponent={<AnotherComponent />} />, document.body);
And then insider the ContainerBox I want to pass AnotherComponent a property in following way.
class ContainerBox extends React.Component {
clickHandler() {
//does something fun
}
render () {
return (
this.props.anotherComponent(this.clickHandler) //<----- is it possible to pass properties from here?
);
}
}
Is it possible to pass things from ContainerBox to AnotherComponent from that position?
ContainerBox has a clickHandler function which I want to pass to AnotherComponent. It is possible to do so if I move <AnotherComponent /> to inside of render() instead. But then I cannot reuse ContainerBox for other components without first copying the whole ContainerBox.
Does it make sense? Hope you can understand.
UPDATED code example
Yes, that is possible. However, it's more common to do it like this
ReactDOM.render(
<ContainerBox><AnotherComponent /></ContainerBox>, document.body);
And in ContainerBox
class ContainerBox extends React.Component {
render () {
return (
this.props.children
);
}
}
Read more about reacts this.props.children here: https://facebook.github.io/react/docs/multiple-components.html#children
Edit:
I just want to point out that in this example, we are not passing a component, but an element (the result of rendering the component).
It's also possible to pass components, like this:
<Foo buttonComponent={FancyButtonComponent} />
and in Foo:
render() {
Button = this.props.buttonComponent;
return (
<div>
...
<Button />
</div>
);
}