Elements of the rendered content of a React component can be bound against properties of the component's state
. Whenever we update the values of state
, we automatically update the content that references its attributes. In this guide, we'll take a look at how to update the rendered content of a component dynamically from data fetched from a third-party API.
The process is as follows:
data
within the component's state
data
state
We'll be using jQuery
as our library to make an HTTP request against an API endpoint.
For this example, we will fetchthe latest Bitcoin price from CoinDesk's public API. Our content will include the price of USD, GBP, and EUR against BTC (Bitcoin). The JSON structure of the data returned by the API endpoint https://api.coindesk.com/v1/bpi/currentprice.json will be as follows:
1{
2 time: {
3 updated: "Sep 16, 2020 18:43:00 UTC",
4 updatedISO: "2020-09-16T18:43:00+00:00",
5 updateduk: "Sep 16, 2020 at 19:43 BST"
6 },
7 disclaimer: "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
8 chartName: "Bitcoin",
9 bpi: {
10 USD: {
11 code: "USD",
12 symbol: "$",
13 rate: "11,091.2212",
14 description: "United States Dollar",
15 rate_float: 11091.2212
16 },
17 GBP: {
18 code: "GBP",
19 symbol: "£",
20 rate: "8,436.3156",
21 description: "British Pound Sterling",
22 rate_float: 8436.3156
23 },
24 EUR: {
25 code: "EUR",
26 symbol: "€",
27 rate: "9,395.0075",
28 description: "Euro",
29 rate_float: 9395.0075
30 }
31 }
32}
Call your component BTCPrice
. Within its constructor, set the value of an attribute data
to have the same structure as the expected return value of the API endpoint.
1import React from 'react';
2import $ from 'jquery';
3
4export default class BTCPrice extends React.Component {
5 constructor(props) {
6 super(props);
7
8 this.state = {
9 data: {
10 time: {
11 updated: "",
12 updatedISO: "",
13 updateduk: ""
14 },
15 disclaimer: "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
16 chartName: "Bitcoin",
17 bpi: {
18 USD: {
19 code: "USD",
20 symbol: "$",
21 rate: "",
22 description: "United States Dollar",
23 rate_float: 0
24 },
25 GBP: {
26 code: "GBP",
27 symbol: "£",
28 rate: "",
29 description: "British Pound Sterling",
30 rate_float: 0
31 },
32 EUR: {
33 code: "EUR",
34 symbol: "€",
35 rate: "",
36 description: "Euro",
37 rate_float: 0
38 }
39 }
40 }
41 }
42 }
43}
The component will render content that references attributes in data
, which can be referenced in turn from the component's state
. Copy the render()
function below and paste it within your component.
1render() {
2 return (
3 <div>
4 <h1>
5 How Much is 1 BTC?
6 <small>
7 {this.sate.data.time.updated}
8 </small>
9 </h1>
10
11 <h2>USD: {this.state.data.bpi.USD.rate}</h2>
12 <h2>GBP: {this.state.data.bpi.GBP.rate}</h2>
13 <h2>EUR: {this.state.data.bpi.EUR.rate}</h2>
14
15 <hr/>
16 <button>
17 Fetch Latest
18 </button>
19 </div>
20 );
21}
Notice how we position the currency's rates within the different HTML dom elements. Think of it as a template wherein the references of data
attributes are placeholders for values that may change whenever the state
of the component is updated. We say that these pieces are bound to the state
. In this case, the attribute values of data
that we will be referencing represent the three different currencies and their rates against Bitcoin, namely:
this.state.data.bpi.USD.rate
for USDthis.state.data.bpi.GBP.rate
for GBPthis.state.data.bpi.EUR.rate
for EURWe also reference the data.time.updated
value at the top to indicate the timestamp for when these prices were taken.
We'll now create our event handler function, which contains logic to make an AJAX request against CoinDesk's API. To do this, copy the following function and paste it within your component.
1fetch() {
2 var context = this;
3
4 $.ajax({
5 url: 'https://api.coindesk.com/v1/bpi/currentprice.json',
6 method: 'GET',
7 dataType: 'json',
8 success: function(response) {
9 context.setState({
10 data: response
11 });
12 }
13 });
14}
There are two key ideas in this function's implementation. First, you create a temporary variable called context
that points to this
referring to the instance of this component. This is needed so that upon a successful AJAX call given by the function(response)
passed to jQuery
's AJAX call's success
property, you can invoke the setState({ data: response })
call from context
. Without context
, this
within function(response)
will refer to the calling function and not the instance of the component. Second, you have to set the dataType
property to json
since we're expecting response
to represent a json
object returned by the API endpoint.
Once setState()
is called, the component will re-render the content with all of the state
's updated values.
The fetch()
method of the component will be triggered every time the user clicks the button. Update the button in HTML within the render()
method of the component and bind the fetch()
method on the button's onClick
attribute.
1<button onClick={this.fetch.bind(this)}>
2 Fetch Latest
3</button>
Include the .bind(this)
function to retain the value of this
when it is used within fetch()
, that is, a reference to the instance of the component.
1import React from 'react';
2import $ from 'jquery';
3
4export default class BTCPrice extends React.Component {
5 constructor(props) {
6 super(props);
7
8 this.state = {
9 data: {
10 time: {
11 updated: "",
12 updatedISO: "",
13 updateduk: ""
14 },
15 disclaimer: "",
16 chartName: "",
17 bpi: {
18 USD: {
19 code: "USD",
20 symbol: "$",
21 rate: "",
22 description: "United States Dollar",
23 rate_float: 0
24 },
25 GBP: {
26 code: "GBP",
27 symbol: "£",
28 rate: "",
29 description: "British Pound Sterling",
30 rate_float: 0
31 },
32 EUR: {
33 code: "EUR",
34 symbol: "€",
35 rate: "",
36 description: "Euro",
37 rate_float: 0
38 }
39 }
40 }
41 }
42 }
43
44 fetch() {
45 var context = this;
46
47 $.ajax({
48 url: 'https://api.coindesk.com/v1/bpi/currentprice.json',
49 method: 'GET',
50 dataType: 'json',
51 success: function(response) {
52 context.setState({
53 data: response
54 });
55 }
56 });
57 }
58
59 render() {
60 return (
61 <div>
62 <h1>
63 How Much is 1 BTC?
64 <small>
65 {this.sate.data.time.updated}
66 </small>
67 </h1>
68
69 <h2>USD: {this.state.data.bpi.USD.rate}</h2>
70 <h2>GBP: {this.state.data.bpi.GBP.rate}</h2>
71 <h2>EUR: {this.state.data.bpi.EUR.rate}</h2>
72
73 <hr/>
74 <button
75 onClick={this.fetch.bind(this)}
76 >
77 Fetch Latest
78 </button>
79 </div>
80 );
81 }
82}
After a user clicks the button, an AJAX call will fetch the data from CoinDesk's API. On success of the call, the component will invoke its setState()
method, causing it to re-render the content with updated values.
You now have the necessary facilities to perform dynamic updating of a component's rendered content. The practice is to maintain a state object within the component. Values from the state object can be referenced in the rendered content. Once an event occurs in any part of the component, the succeeding logical process will be to update any values within the state if needed. An update in the state will cause a re-rendering of the content with all the updated values without needing a refresh to the page or manually target DOM elements and update its inner content.