score:266
try:
var wrapper = react.createclass({
render: function() {
return (
<div classname="wrapper">
before
{this.props.children}
after
</div>
);
}
});
see multiple components: children and type of the children props in the docs for more info.
score:31
in addition to sophie's answer, i also have found a use in sending in child component types, doing something like this:
var listview = react.createclass({
render: function() {
var items = this.props.data.map(function(item) {
return this.props.delegate({data:item});
}.bind(this));
return <ul>{items}</ul>;
}
});
var itemdelegate = react.createclass({
render: function() {
return <li>{this.props.data}</li>
}
});
var wrapper = react.createclass({
render: function() {
return <listview delegate={itemdelegate} data={somelistofdata} />
}
});
score:188
using children
const wrapper = ({children}) => (
<div>
<div>header</div>
<div>{children}</div>
<div>footer</div>
</div>
);
const app = ({name}) => <div>hello {name}</div>;
const wrappedapp = ({name}) => (
<wrapper>
<app name={name}/>
</wrapper>
);
render(<wrappedapp name="toto"/>,node);
this is also known as transclusion
in angular.
children
is a special prop in react and will contain what is inside your component's tags (here <app name={name}/>
is inside wrapper
, so it is the children
note that you don't necessarily need to use children
, which is unique for a component, and you can use normal props too if you want, or mix props and children:
const applayout = ({header,footer,children}) => (
<div classname="app">
<div classname="header">{header}</div>
<div classname="body">{children}</div>
<div classname="footer">{footer}</div>
</div>
);
const appelement = (
<applayout
header={<div>header</div>}
footer={<div>footer</div>}
>
<div>body</div>
</applayout>
);
render(appelement,node);
this is simple and fine for many usecases, and i'd recommend this for most consumer apps.
render props
it is possible to pass render functions to a component, this pattern is generally called render prop
, and the children
prop is often used to provide that callback.
this pattern is not really meant for layout. the wrapper component is generally used to hold and manage some state and inject it in its render functions.
counter example:
const counter = () => (
<state initial={0}>
{(val, set) => (
<div onclick={() => set(val + 1)}>
clicked {val} times
</div>
)}
</state>
);
you can get even more fancy and even provide an object
<promise promise={somepromise}>
{{
loading: () => <div>...</div>,
success: (data) => <div>{data.something}</div>,
error: (e) => <div>{e.message}</div>,
}}
</promise>
note you don't necessarily need to use children
, it is a matter of taste/api.
<promise
promise={somepromise}
renderloading={() => <div>...</div>}
rendersuccess={(data) => <div>{data.something}</div>}
rendererror={(e) => <div>{e.message}</div>}
/>
as of today, many libraries are using render props (react context, react-motion, apollo...) because people tend to find this api more easy than hoc's. react-powerplug is a collection of simple render-prop components. react-adopt helps you do composition.
higher-order components (hoc).
const wraphoc = (wrappedcomponent) => {
class wrapper extends react.purecomponent {
render() {
return (
<div>
<div>header</div>
<div><wrappedcomponent {...this.props}/></div>
<div>footer</div>
</div>
);
}
}
return wrapper;
}
const app = ({name}) => <div>hello {name}</div>;
const wrappedapp = wraphoc(app);
render(<wrappedapp name="toto"/>,node);
an higher-order component / hoc is generally a function that takes a component and returns a new component.
using an higher-order component can be more performant than using children
or render props
, because the wrapper can have the ability to short-circuit the rendering one step ahead with shouldcomponentupdate
.
here we are using purecomponent
. when re-rendering the app, if the wrappedapp
name prop does not change over time, the wrapper has the ability to say "i don't need to render because props (actually, the name) are the same as before". with the children
based solution above, even if the wrapper is purecomponent
, it is not the case because the children element is recreated everytime the parent renders, which means the wrapper will likely always re-render, even if the wrapped component is pure. there is a babel plugin that can help mitigate this and ensure a constant children
element over time.
conclusion
higher-order components can give you better performance. it's not so complicated but it certainly looks unfriendly at first.
don't migrate your whole codebase to hoc after reading this. just remember that on critical paths of your app you might want to use hocs instead of runtime wrappers for performance reasons, particularly if the same wrapper is used a lot of times it's worth considering making it an hoc.
redux used at first a runtime wrapper <connect>
and switched later to an hoc connect(options)(comp)
for performance reasons (by default, the wrapper is pure and use shouldcomponentupdate
). this is the perfect illustration of what i wanted to highlight in this answer.
note if a component has a render-prop api, it is generally easy to create a hoc on top of it, so if you are a lib author, you should write a render prop api first, and eventually offer an hoc version. this is what apollo does with <query>
render-prop component, and the graphql
hoc using it.
personally, i use both, but when in doubt i prefer hocs because:
- it's more idiomatic to compose them (
compose(hoc1,hoc2)(comp)
) compared to render props - it can give me better performances
- i'm familiar with this style of programming
i don't hesitate to use/create hoc versions of my favorite tools:
- react's
context.consumer
comp - unstated's
subscribe
- using
graphql
hoc of apollo instead ofquery
render prop
in my opinion, sometimes render props make the code more readable, sometimes less... i try to use the most pragmatic solution according to the constraints i have. sometimes readability is more important than performances, sometimes not. choose wisely and don't bindly follow the 2018 trend of converting everything to render-props.
Source: stackoverflow.com
Related Query
- React.js: Wrapping one component into another
- How to access state of one component into another component in react
- React couldn't pass a data from one class component into another using Link
- How to pass in a react component into another react component to transclude the first component's content?
- Is it safe to render a react portal into another component DOM?
- How to replace a component with another one upon event (button click) in react js
- Sizing one component by getting the width of another one using useRef hook in React
- React - toggle display of one component from the onClick of another component
- how to send value one component to another component in react js?
- Animate movement of React component from one to another
- How to from one component set state another component in react native?
- How to pass data from one component to another in React or React-Redux?
- One react app imported into another react app?
- Redirect automatically from one component to another one after few seconds - react
- How does one React component call a method in another React component?
- How to replace one React Component with another OnClick?
- Dynamically insert react components into another react component
- Best practice way to set state from one component to another in React
- In Flux what's the appropriate way for an action in one React component to affect another component?
- How to refresh data of one component from another component in react js
- React collect all properties as one props and put it into component or NOT?
- In React, how do I call a function in one component (which is being rendered with React Router) from another component?
- Passing data from one component to another - React & Redux
- React | pass form data from one component to another
- add attributes to a react component passed into another component via props
- What's the best way to inject a React component into another React component? Or should I bother?
- Routing from one component to another in React
- Passing instance variables from one child component to another in React
- exporting React component class with one name, importing it with another name, still working. Why?
- React passing data into another component
More Query from same tag
- React adding FloatingMenuButton Package Parsing error: Unexpected token
- Using web3modal in class component shows state error
- How to add items to array in react
- How to update a specific object within storage with React/Redux?
- Perform 2 functions OnClick ReactJS
- How to use fetch correctly?
- 404 for all routes with included locale - NextJS with next-i18next
- How do I check the attribute value of a div in React
- Get InputBase value out from the same component
- React/Mobx: Selecting item in an array
- Checkbox not reflecting changes in the state in ReactJS
- Change NavLink text Color onClick
- structure of img directory react.js
- base64 encoded image not dispaying in material ui CardMedia
- Why do I have to use "require" instead of "import from" for an image in React?
- SSR + Material UI Drawer + webpack production build broken
- Break apart giant global-style, retaining access to the theme context
- onClick in Map func,only execute for one element
- React Leaflet Not Showing Map Correctly
- not able to get choice group target id to set values dynamically
- search engine - the state has a different value than input
- Page works on local host but not firebase or netlifly
- How to solve the issue? Access to XMLHttpRequest'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
- .modal-content for different Modals (react-bootstrap)
- Issue with MUI 5 datePikker when we add inputFormat
- How to save current user data using react-redux?
- Image not getting displayed when using Reactjs map function. Error--SRC undefined
- In React, is it possible to alter state inside of the map method, and if not what is an alternative?
- TypeError: undefined is not an object (evaluating 'this.setState')
- After an check if something is not null I get a null or undefined type error. How?