I am new to react and seen following declaration in few tutorials.
I am confuse on which to use. Is there any guideline on which to prefer under difference situation?
Declaration 1
const elem = function() {
return <div>Hello World!</div>
}
Declaration 2
const elem2 = <div>Hello World!</div>
Declaration 3
class App extends Component {
render() {
return (
<div>Hello World!</div>
);
}
}
Considering
class App extends Component {
render() {
return (
<div>Hello World!</div>
);
}
}
is a React component and hence should be used when you wish to create separate Components for different functionalities for you Application which includes states and props being passed.
As per
const elem2 = <div>Hello World!</div>
it should be used when the JSX elements do not contain extra logic and contian static contents
const elem = function() {
return <div>Hello World!</div>
}
should ideally be used when you want to perform certain modification on the data and return the JSX element, also if you wish to perform some conditional returns and stateless retuns
You can always use functional components when the component is composed only from the render function.
That means, if your component has the following form:
class MyComponent extends React.Component {
render() {
... do something ...
}
}
then you can replace it with
const MyComponent = (props, context) => {
... do something ...
}
Functional components cannot have state (they are stateless) and you cannot access the component lifecycle (e.g. componentDidMount). You also cannot use pure rendering with them because you cannot override shouldComponentUpdate.
They are the purest form of a component, they convert properties into UI and have no other side-effects.
I would recommend to use them as much as possible because they enforce a good programming style (especially with redux architecture) but you won't be able to use them everytime. The "smarter" a component is, the less possible it will be to use a functional component (see Smart vs Dumb components).
They are especially useful when defining Higher Order Components.
Also note that you can often combine all approaches, consider
render() {
const renderContents = () => {
return (
<div className="contents">
this.props.children
</div>
);
}
return (
<div>
{renderContents}
</div>
);
}
You can define a "component" inside other component's render. As you can see, there is no difference between a function and a functional component. And the same applies for constants. Defining a constant <div /> is not different from defining a constant string or a number. You don't need to wrap it into a component/function. You can also do things like this:
const contents = (() => {
if (props.children.count === 0) {
return null;
}
return (
<div>{props.children}</div>
);
})();
This is an immediately invoked function.
Related
Sometimes I want to move my conditional rendering out of render(), and I always have dilemma between these two approaches:
class MyComponent extends React.Component {
_renderSomething() => {
const {x, y, z} = this.props
// conditional rendering based on props
}
render() {
return (
{ this._renderSomething }
// vs
{ renderSomething(this.props) }
// which one is better?
)
}
}
const renderSomething = (props) => {
const {x, y, z} = props
// conditional rendering based on props
}
export default MyComponent
Any performance difference between _renderSomething and this.renderSomething?
When should I use which?
There is a performance penalty with Functional Components vs Functions returning elements. An example would be this -
// Component approach
let Tab = ({label, link}) => <li><a href={link}>{label}</a></li>;
class Tabs extends Component {
render(){
return (
// notice the key prop is handled by parent render
<ul>{this.props.tabs.map(tab => <Tab {...tab} key={link}>)}</ul>
)
}
}
// function based approach, notice the key prop is handled by the function
let tab = ({label, link}) => <li key={link}><a href={link}>{label}</a></li>;
class Tabs extends Component {
render(){
return (
<ul>{this.props.tabs.map(item => tab(item))}</ul>
)
}
}
In Component example, you will end up with unnecessary intermediate Tab components, which will add to the virtual dom, however small they are. And then as they grow, these components will eventually cause slow renders. React will need to keep track of these components over subsequent renders. And these being functional components, you would not have access to shouldComponentUpdate based optimizations.
The function version will not suffer from this as it returns Elements directly, instead of components. Also, with smaller functions, there will be gains due to code inlining.
An extended discussion into this approach is here.
in general, a stateless component should probably be a pure function that just returns the component to render
Below, you could replace <EmptyList /> with <ul></ul> but the idea is you can abstract wherever you feel is necessary – in this case, I thought it would be nice to have some placeholder text for empty lists, so making it a stateless functional component was an easy choice
So little of your app actually needs state – in fact, you should be striving to remove it wherever possible. When nothing needs state, everything can be expressed with functions
const EmptyList = ({ placeholder = "There are no items to display" }) =>
<ul><li>{ placeholder }</li></ul>
const ListItem = ({ text = "" }) =>
<li>{ text }</li>
const List = ({ items = [] }) =>
items.length === 0
? <EmptyList />
: <ul>{ items.map (text => <ListItem text={text} />) }</ul>
ReactDOM.render(<List items={[1,2,3]} />, document.querySelector('#list1'))
ReactDOM.render(<List items={[]} />, document.querySelector('#list2'))
<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="list1"></div>
<div id="list2"></div>
Looking at this simple example where the prop toggleData would be a redux thunk action mapped to the container props.
Is this the recommended way to pass a function like this to a child 'dumb' component? I read an article online saying that using arrow functions inside handlers is expensive and not very efficient from a performance perspective.
class Container extends React.Component {
render(){
return (
<Home toggleData={this.props.toggleData}/>
)
}
}
const Home = (props) => {
return (
<button onClick={()=>{props.toggleData()}}></button>
)
}
Yes! Avoid using arrow functions inside the JSX. Because the function will be created on every render, this might lead to performance issues later on.
If you don't need to send parameters you can do something like this:
const Home = (props) => {
return (
<button onClick={props.toggleData}></button>
)
}
If you need to use parameters, I usually define a class to create the callback using an arrow function, this way it gets created and bound only once.
class Home extends PureComponent {
onToggle = () => {
this.props.toggleData(1, 2, 3);
}
render() {
return (
<button onClick={this.onToggle}></button>
)
}
}
I have a container component which passes an array of objects down to a presentational component to output.
In the presentational component, I need to display the count of a number of these objects that meet certain criteria. Is it best practice to perform the count in the container component and pass it down to the presentational component or is it OK to do this count in the presentational component.
ie:
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
countSexyObjects(){
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy === true;
});
return matching.length
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects}
numberOfSexyObjects={this.countSexyObjects()} />
);
}
}
let PresentationalComponent = (props) => {
return (
<div>
There are {props.numberOfSexyObjects} sexy objects
</div>
);
};
OR
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects} />
);
}
}
let PresentationalComponent = (props) => {
const countSexyObjects = () => {
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy === true;
});
return matching.length
};
return (
<div>
There are {countSexyObjects()} sexy objects
</div>
);
};
Ideally state is considered an evil in React. I understand that React is built upon the concept of state but less state is more preferred, which means try to structure the code with mostly functions that are pure in nature.
IMHO in your first example is more correct. The ResultsPage is your Container Component(smart component) while the other is dumb. Dumb component doesn't manage state and just takes care of how the UI looks. You can put all the html, bootstrap logic in there.
The reason why this pattern is good is because lets say now you want to fetch the matching criteria from an XHR call, your code in the second case would be
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
getSexyMatcher() {
/* make ajax call here */
return results;
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects} sexyMatcher={getSexyMatcher()}/>
);
}
}
let PresentationalComponent = (props) => {
const countSexyObjects = () => {
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy.match(props.sexyMatcher)
// return obj.sexy === true;
});
return matching.length
};
return (
<div>
There are {countSexyObjects()} sexy objects
</div>
);
};
Notice how you had to change two components for the same business logic? Much worse, what if someone else used that PresentationalComponent elsewhere in the codebase?
In the first case things are much simpler. Just have to add the ajax function in the smart component and pass down the results to the UI component.
I would use the first format for a few reasons:
The smart component should a better idea of what a "SexyObject" is. If its a field in the object, that's pretty simple and could be argued either way. If it relies on a web service or some more complex logic to determine if it is sexy or not, you would never want that in the presentational layer. Simple has a way of turning complex, so I'd use the structure that supports the complexity initially.
Testing the code will be simpler with the logic in the smart component. You can prime your component and then check the output variables from your fixed data set.
If the criteria for "SexyObject" can change by the component, you would retain the ability to reuse your presentational component if you kept the selection logic separate.
Just my $0.02
I'd like to create a super general component that can be built with any element type. ie, I'd like to do something like this:
const Wrapper = React.createClass({
render() {
const { props } = this;
const elementType = props.elementType;
return (
<{elementType} className={className}>
{props.children}
</{elementType}>
);
}
});
but of course React gets very angry when I attempt this. Is there any way to build a component with to-be-decided HTML types?
This depends very much on what elementType is. In JSX, you can either pass in a custom component itself, or a string (e.g. h1, p) as a "tag". In any case, you don't want to put the curly brackets {} around the tag. Very simple example:
// Usually you want to import this. (This is just a stateless component)
const Element = (props) => <em>{props.children}</em>;
class Example extends React.Component {
constructor() {
super();
this.state = { element1: 'h1', element2: Element };
}
render() {
return(
<div>
<this.state.element1>Hello!</this.state.element1>
<this.state.element2>World!</this.state.element2>
</div>
);
}
}
ReactDOM.render(<Example />, document.getElementById('View'));
<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='View'></div>
If you want to use a string as a reference to a custom component, you will need to use native JavaScript with React's createElement/cloneElement.
You can use React.createElement to accomplish that (after all, JSX just provides syntactic sugar for it).
Something like that:
const myElement = React.createElement(
/* type */
props.elementType, //must be a string or a React Component class
/* props object */
{
className: className
},
/* You can pass children to the third parameter also. */
props.children
);
return myElement;
Yes, you can — even with JSX if you'd like.
The trick is to understand how JSX is translated into the React.createElement calls:
bracketed text starting with a lowercase character is translated into a string: <div/> becomes React.createElement('div').
bracketed text starting with an uppercase is assumed to be a variable in scope: <SomeComponent/> becomes React.createElement(SomeComponent).
Now imagine if you assign var SomeComponent = 'div'. Then the uppercase rule would apply (passing the variable to createElement), but it will have the same effect as the first rule (because the variable references a string)!
Here's how it can look in a practical situation:
let Child = ({EL,thing}) => <EL className="helper-thing">{{ thing.name }}</EL>
let ListParent = ({things}) => <ul>
{things.map(t => <Child EL='li' thing={t}/>)}
</ul>
let ArticleParent = ({things}) => <article>
{things.map(t => <Child EL='p' thing={t}/>)}
</article>
See the official docs on Choosing the Type at Runtime for a slightly different — perhaps cleaner — approach that capitalizes the property inside the child component.
JSX does not allow this, but you can do it in pure Javascript React. You can create the component:
const element = React.createElement(elementType, {className}, props.children);
then return element from your render method. In fact, this is more or less what JSX would compile to, if it allowed you to do what you're proposing.
See https://facebook.github.io/react/docs/react-without-jsx.html for more discussion.
If I simply have:
const App = function() {
return (
<div>{this.renderList()}</div>
)
}
How do I define the renderList method?
I can't do const renderList = function() {} (nor with var or let). I can't do renderList() {}.
What's the right syntax?
I am hesitant to give a solution to this because inline Stateless Functions are not supposed to have methods. if you want a method you should use a Class and theres nothing wrong with using a class. Its all based on what you need to do. Stateless Functions are designed to be a super light weight way to render something that doesn't need methods, or a state or even a this context (in terms of a class).
you should be doing it like this.
class App extends Component {
constructor(){
super();
// note this is a Stateless Component because its a react class without a state defined.
}
renderList = () => {
return <span>Something Here</span>;
}
render() {
return <div>{this.renderList()}</div>
}
}
a HACK way that I wouldn't recommend (but does solve your question in the way you want it to) would be like this.
const App = () => {
let renderList = () => {
return <span>Something Here</span>
}
return <div>{renderList()}</div>
}
The reason why its generally a bad practice is because you are creating a function and all the memory allocation needed every render cycle. Subsequently, the internal diffing optimizations that react provides is generally useless if you do this because a new function gives a different signature than the prior render cycle. If this had a lot of children, they would all be forced to re-render!
Edit - React Version 16.8.0 +
You can use Hooks to do this. I would recommend using memo to memoize the function, this way you aren't creating it in memory each render cycle.
const RenderList = React.memo(props => (
<span>Something Here</span>
))
const App = function() {
const renderList = ()=> {
return "this variables"
}
return (
<div>{renderList()}</div>
)
}
You would want to do something like this
const App = function() {
return (
<div>{renderList()}</div>
)
}
function renderList(){
return "this variables"
}
Naturally this is a bad approach you its recommended that you pass in functions as props and stateless component are always dumb componets. Say if you are using redux for example you can have your component render like this
import {connect} from 'react-redux';
const App = (props) => {
return (
<div> {props.renderList} </div>
)
}
function renderList (){
return "your render logic"
}
export default connect(null, {renderList})(App)
Can you try something like
const App = () => {
return (
<div>{this.renderList()}</div>
)
}
App.renderList = () => {
return 'This is my list'
}
You can create render list function as standalone and use function parameter to pass props into function.