Skip to content

Commit e172f5f

Browse files
committed
add render-callback.html
1 parent 42665ab commit e172f5f

9 files changed

+165
-24
lines changed

accessing-a-child-component.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
<h3>Accessing a child component</h3>

async-initialization-in-componentdidmount.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
<h3>Async initialization in componentDidMount()</h3>

container-component.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
<h3>Container component</h3>

functional-setstate-(pass-a-function-to-setstate).html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
<h3>Functional setState (Pass a function to setState)</h3>

higher-order-component.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
<h3>Higher Order Component - Props proxy</h3>

higher-order-function.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
<h3>Higher order function</h3>

index.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
</div>

jsx-spread-attributes.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ <h3>Table of Contents</h3>
1919
<ul>
2020
<ul>
2121
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22-
<li><a href="container-component.html">Container component</a></li>
23-
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2422
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
25-
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
2623
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
2726
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
2829
</ul>
2930
</ul>
3031
<h3>JSX spread attributes</h3>

render-callback.html

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<html>
2+
<head>
3+
<title>Render callback | React Patterns & Techniques</title>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
6+
<meta name="description" content="Render callback">
7+
<meta name="keywords" content="react-patterns, patterns, react, javascript, react-native, reactjs, component, components, front-end, frontend, front-end-development, frontend-web, frontend-webdevelopment, frontend-components, frontend-app, react-app, react-component, react-components, react-techniques, reactjs-patterns">
8+
<meta name="Code Facebook" content="[email protected]">
9+
<link href="css/styles.css" rel="stylesheet">
10+
</head>
11+
<body>
12+
<div id="container">
13+
<header>
14+
<h1>
15+
<a href="/">React Patterns & Techniques</a>
16+
</h1>
17+
</header>
18+
<h3>Table of Contents</h3>
19+
<ul>
20+
<ul>
21+
<li><a href="async-initialization-in-componentdidmount.html">Async initialization in componentDidMount()</a></li>
22+
<li><a href="functional-setstate-(pass-a-function-to-setstate).html">Functional setState (Pass a function to setState)</a></li>
23+
<li><a href="higher-order-function.html">Higher order function</a></li>
24+
<li><a href="higher-order-component.html">Higher Order Component - Props proxy</a></li>
25+
<li><a href="accessing-a-child-component.html">Accessing a child component</a></li>
26+
<li><a href="jsx-spread-attributes.html">JSX spread attributes</a></li>
27+
<li><a href="render-callback.html">Render callback</a></li>
28+
<li><a href="container-component.html">Container component</a></li>
29+
</ul>
30+
</ul>
31+
<h3>Render callback</h3>
32+
<p>
33+
Take a look at the example below. Notice that we create a function <code>foo</code> which takes a callback function as a parameter. When we call <code>foo</code>, it turns around and "calls back" to the passed-in function.
34+
</p>
35+
<pre class="screen">
36+
const foo = (hello) => {
37+
return hello('foo');
38+
};
39+
40+
foo((name) => {
41+
return `hello from ${name}`;
42+
});
43+
44+
// hello from foo
45+
</pre>
46+
<p>
47+
As you can see, <code>foo</code> used the callback function to complete a portion of a string. In the React world, a render callback works the same way, but returning a portion of the rendered markup.
48+
</p>
49+
<p>
50+
Here’s what we would like to use it:
51+
</p>
52+
<pre class="screen">
53+
const App = () => {
54+
return (
55+
&lt;div&gt;
56+
&lt;FieldItem username='Bunlong'&gt;
57+
{user => user === null ? &lt;Loading /&gt; : &lt;Profile info={user} /&gt;}
58+
&lt;/FieldItem&gt;
59+
&lt;/div&gt;
60+
);
61+
};
62+
</pre>
63+
<p>
64+
<code>FieldItem</code> will render either the <code>Loading</code> or the <code>Profile</code> component, depending on the existence of a <code>user</code> property. It also passes down a prop of its own, <code>username</code>, that one of these components can consume to make a call.
65+
</p>
66+
<p>
67+
What is interesting here is that <code>&lt;FieldItem/&gt;</code> uses a function as a child. Any child component inside it is now free to consume this prop however it needs to, totally decoupled from the parent.
68+
</p>
69+
<p>
70+
To make it work, the key is to treat <code>this.props.children</code> as a function. So in order for the <code>Profile</code> component to render whatever it needs to render, it needs to run the callback on the <code>children</code> function, passing it the <code>user</code> argument it expects. Here’s an example implementation of <code>Profile</code>:
71+
</p>
72+
<pre class="screen">
73+
class FieldItem extends React.Component {
74+
state = { user: null }
75+
76+
componentDidMount() {
77+
// We can make an ajax call here, for e.g.
78+
setTimeout(() => this.setState({
79+
user: `I have now fulfilled something for ${this.props.username}`
80+
}), 1500);
81+
}
82+
83+
render() {
84+
// Render the children with a function using state as the argument
85+
return this.props.children(this.state.user);
86+
}
87+
}
88+
</pre>
89+
<p>
90+
The key there is the child component rendering <code>return this.props.children(this.state.user)</code> with its own state. This means its up to the component to decide how to use the arguments it receives, and the parent component <code>FieldItem</code> doesn’t care: it only manages which component to render, in this case.
91+
</p>
92+
<p>
93+
Looking at <code>Profile</code>, since <code>user</code> is <code>null</code> for 1000ms, the callback receives null as a value for user, thus rendering <code>&lt;Loading /&gt;</code> first. Once we have a <code>user</code>, the Profile component will then render. I really enjoy the simplicity and the cleanliness of this approach managing components.
94+
</p>
95+
<pre class="screen">
96+
// Loading component
97+
const Loading = () => &lt;p&gt;Loading...&lt;/p&gt;;
98+
99+
// Profile component
100+
const Profile = (props) => &lt;p&gt;{props.info}&lt;/p&gt;;
101+
102+
const App = () => {
103+
return (
104+
&lt;div&gt;
105+
&lt;h3&gt;An application&lt;/h3&gt;
106+
&lt;FieldItem username='magalhini'&gt;
107+
{ user => user === null ? &lt;Loading /&gt; : &lt;Profile info={user} /&gt; }
108+
&lt;/FieldItem&gt;
109+
&lt;/div&gt;
110+
);
111+
};
112+
113+
class FieldItem extends React.Component {
114+
state = { user: null }
115+
116+
componentDidMount() {
117+
// We can make an ajax call here, for e.g.
118+
setTimeout(() => this.setState({
119+
user: `I have now fulfilled something for ${this.props.username}`
120+
}), 1500);
121+
}
122+
123+
render() {
124+
// Render the children with a function using state as the argument
125+
return this.props.children(this.state.user);
126+
}
127+
}
128+
129+
ReactDOM.render(&lt;App/&gt;, document.getElementById('app'));
130+
</pre>
131+
</div>
132+
</body>
133+
</html>

0 commit comments

Comments
 (0)