ma

The man who grew his own Amazon rainforest

Fighting back against destruction in the Amazon: how one man grew a rainforest of his own.




ma

From patient to healer: How this woman is saving lives

Women who have overcome depression are running therapy sessions to help others




ma

Ultra-Orthodox and trans: 'I prayed to God to make me a girl'

Growing up as a Hasidic Jew, Abby Stein had no idea trans people existed - she just felt sure she was a girl.




ma

Ramadan and Coronavirus: Breaking my fast on Zoom

How fasting in lockdown and isolation has changed Ramadan for young Muslims this year.




ma

Coronavirus career pivots: 'I now work in a supermarket'

An actress and a commercial sales leader talk about making the switch to working in a supermarket.




ma

Coronavirus tests and masks sold by fraudsters online

A BBC investigation has found online scams selling fake protective equipment and coronavirus tests.




ma

Coronavirus: UK chancellor on new microloan scheme for small businesses

Firms will be able to borrow up to £50,000, which will be interest free for the first year.




ma

Coronavirus: Should maternity and paternity leave be extended?

A petition calling for maternity leave to be extended due to coronavirus has attracted many signatures.




ma

Staging a 'socially distanced' boxing match

Inside the Nicaraguan boxing event that caught the world's attention during the pandemic.




ma

Coronavirus: Disease meets deforestation at heart of Brazil's Amazon

Coronavirus has overwhelmed Manaus, the Amazon's biggest city, and the worst is yet to come.




ma

Millie Small: My Boy Lollipop singer dies aged 72

The singer, who had Jamaica's first million-selling single, dies after suffering a stroke.




ma

Brazil's Amazon: Surge in deforestation as military prepares to deploy

The military is preparing to deploy to the region to try to stop illegal logging and mining.




ma

How to Make Your React Apps 15x Faster

Without any modifications, React is really fast as-is. There are, however, a few things that you can do to improve performance. While working at HelloSign, I discovered some quick fixes that made our apps incredibly snappy. With these simple changes, I was able to reduce render time from over 3000 milliseconds to less than 200 milliseconds.

Without any modifications, React is really fast as-is. There are, however, a few things that you can do to improve performance. While working at HelloSign, I discovered some quick fixes that made our apps incredibly snappy. With these simple changes, I was able to reduce render time from over 3000 milliseconds to less than 200 milliseconds.

Editor’s Note:

Check out our upcoming React University Workshops. Our next workshop, React 2016, will be held on April 23 at Microsoft Reactor in San Francisco and will offer a deep dive into creating modern Single-Page Applications (SPA) using React, Redux, React Router, Immutable.js, and Webpack. Also, if you’re interested in learning the basics about what it takes to be a Data Visualization Engineer, check out React and D3.

Introduction

HelloSign is a cloud-based electronic signature tool founded in 2010. As you can imagine, HelloSign is a very JavaScript-heavy codebase. A lot of client-side behavior is necessary to create a rich signing experience. Lately, we’ve moved much of our codebase toward React. In fact, in many places we’ve broken up our codebase into several single-page applications written in React.

Although the HelloSign team was happy with React’s performance before I initially joined the project, I quickly found some low-hanging fruit that could improve runtime speed. Here are the steps you should take to see similar improvements in your own applications.

Create a Baseline Performance Measurement

Before you begin, you should take a baseline measurement. Optimizations are meaningless if you can’t verify the results of your modifications.

Thankfully, Chrome has excellent developer tools to help. One, little-used feature of Chrome’s DevTools is the “Timeline” tool. It allows you to record and analyze all activity in your application. You can record interactions on the page, locate potential memory leaks, measure the total time it takes to perform a task, and identify areas of potential jank. Best of all, the results can be recorded for comparison with your final benchmark.

There’s actually a really awesome video on Chrome’s DevTools that goes into detail about the “Timeline” feature. You can view it here.

We chose to measure the time elapsed between the initial paint of our signer page to the final rendering of the entire page. The initial download of our bundles still needs some optimization, but we’re neither going to mess with nor measure this parameter. It’s fairly easy and consistent to test render time rather than trying to click areas around the page and trying to measure its performance in a repeatable way. Then, all we needed to do was to go to the signer page, open Chrome’s DevTools “Timeline” tab, and refresh the page.

As a side note, make sure that when performing this test, the “Paint” and “Screenshots” boxes are checked so that you can see what the user sees as the page is being rendered.

After all that, we determined that our rendering time from initial paint was a little over 3 seconds. Much too long. Luckily, there was little we had to do to make this quite a bit faster.

Set NODE_ENV to Production

This step is easy to get wrong, even if you are well-informed. React’s documentation provides an overview, but doesn’t provide many specifics. React has great developer warnings and error checking, but these are only intended for development; if you take a look at React’s source code, you’ll see a lot of if (process.env.NODE_ENV != 'production') checks. This is running extra code that is not needed by the end user, not to mention that calling process.env.NODE_ENV is extremely slow. For production environments, we can remove all this unnecessary code. Just keep in mind that you don’t want to do this in development because it will remove all those helpful developer warnings.

If you’re using Webpack, you can use DefinePlugin to replace all instances of process.env.NODE_ENV with 'production', and then use the UglifyJsPlugin to remove all the dead code that no longer runs. Here’s a sample setup that you might use:

// webpack.config.js
  ...
  plugins: [
    new webpack.DefinePlugin({
      // A common mistake is not stringifying the "production" string.
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
  ...

React Constant and Inline Elements Transforms

React 0.14 introduced support for certain transpile time optimizations with Constant and Inline Element Babel Transforms. React Constant Elements treats JSX elements as values and hoists them to a higher scope. In other words, it hoists static elements and thereby reduces calls to React.createClass. React Inline Elements converts JSX elements into the object literals that they eventually return. Again, this minimizes the runtime calls to React.createClass.

The implementation is rather simple. We added our Babel configuration in our package.json file:

// package.json
  ...
  "babel": {
    "env": {
      "production": {
        "plugins": [
          "transform-react-constant-elements",
          "transform-react-inline-elements"
        ]
      }
    }
  },
  ...

Final Measurement / Conclusion

Lastly, you’ll want to run the benchmark again and compare it with that saved benchmark from before these optimizations. As you can see, the total runtime profile ends 200ms after initial paint! That’s 15 times faster!




ma

Leveraging React for Easy Image Management

React is a good tool when it comes to building flexible and reusable UI components. However, it’s “one of those libraries” that cannot handle all the tasks involved in building a full fleshed UI project. Other supporting tools - such as a recently announced React SDK from Cloudinary - are available to provide solutions that the React core cannot.

In such cases where media (images and videos) becomes a heavy task to handle, Cloudinary simplifies the process with the new React SDK. Let’s build and image library with Cloudinary and React using the Cloudinary’s React SDK.

Prerequisites

The only requirements for using Cloudinary in your existing React project are to install the React SDK and the upload widget. If you do not have an existing React project and want to try these examples, take the following steps:

1. Install Dependencies

We need a minimal amount of dependencies so we can focus on building a media library and not structuring a React app:

{
  "name": "img-library",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch": "webpack -d --watch",
    "build": "webpack",
    "serve": "serve ./public"
  },
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "babel-core": "^6.18.2",
    "babel-loader": "^6.2.9",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-react": "^6.16.0",
    "serve": "^1.4.0",
    "webpack": "^1.14.0"
  },
  "dependencies": {
    "axios": "^0.15.3",
    "cloudinary-react": "^1.0.1",
    "react": "^15.4.1",
    "react-dom": "^15.4.1"
  }
}

React (and React DOM) must be used since we are making a React app. The cloudinary-react dependency is Cloudinary’s React SDK, which we will soon see how it works. axios is a tool for making HTTP requests and, in our case, we will use it request images from the Cloudinary server.

# Install dependencies
npm install

2. Setup Webpack

Webpack is our build tool. Only minimal settings are required to have a build running and our React app compiling:

// ./webpack.config.js
var webpack = require('webpack');
var path = require('path');

var BUILD_DIR = path.resolve(__dirname, 'public');
var APP_DIR = path.resolve(__dirname, 'src');

var config = {
    entry: APP_DIR + '/index.jsx',
    output: {
        path: BUILD_DIR,
        filename: 'bundle.js'
    },
    module : {
        loaders : [
            {
                test : /.jsx?/,
                include : APP_DIR,
                loader : 'babel'
            }
        ]
    }
};

module.exports = config;

Basic configuration - an entry, output and loaders to handle the React .jsx files.

3. Entry Points

We need to create an entry point, as we specified in the Webpack configuration, and another entry point for the browser, which is an index.html file:

// ./src/index.jsx
import React, { Component } from 'react';
import { render } from 'react-dom';

class Main extends Component {
    render() {
        return (
           <div className="main">
               <h1>Scotchage</h1>
           </div>
        );
    }
}

render(<Main />, document.getElementById('container'));
<!-- ./public/index.html -->
<html>
<head>
    <!--Stylesheet-->
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <!--Container for React rendering-->
    <div id="container"></div>
    <!--Bundled file-->
    <script src="bundle.js"></script>
</body>
</html>

4. Create Cloudinary Account

You need a Cloudinary account to continue with these examples. Sign up for free and store your credentials safely as shown on the dashboard:

Uploading Images

Before using the React SDK to deliver images from the Cloudinary servers, let’s use the awesome Cloudinary upload widget to upload images. First, we need to add this widget to our index.html:

<!-- ./public/index.html -->
<html>
<head>
   . . .
</head>
<body>
    . . .
    <!-- UPLOAD WIDGET -->
    <script src="//widget.cloudinary.com/global/all.js" type="text/javascript"></script>
    <script src="bundle.js"></script>
</body>
</html>

Next, we create a button, attach an event to it and upload an image once the button is clicked:

import React, { Component } from 'react';
import { render } from 'react-dom';

class Main extends Component {

    uploadWidget() {
        cloudinary.openUploadWidget({ cloud_name: 'CLOUD_NAME', upload_preset: 'PRESET', tags:['xmas']},
            function(error, result) {
                console.log(result);
            });
    }
    render(){
        return (
            <div className="main">
                <h1>Galleria</h1>
                <div className="upload">
                    <button onClick={this.uploadWidget.bind(this)} className="upload-button">
                        Add Image
                    </button>
                </div>
            </div>

        );
    }
}

render(<Main />, document.getElementById('container'));

The uploadWidget member method is the handler invoked by the click event to handle our image upload by calling cloudinary.openUploadWidget. openUploadWidget takes a config object and the upload callback handler. The config object must have at least cloud_name and upload_preset properties with valid values. You can read more about Cloud Names and Upload Presets.

Delivering Images with SDK

The Cloudinary React SDK has three major components, Image, CloudinaryContext and Transformation:

  • Image: This component is responsible for the actual delivery of images. It takes the image ID and asks the server for this image. When the image is provided, it is also responsible for painting the image on the browser.
  • Transformation: This component is used to apply transformations to images delivered with Image.
  • CloudinaryContext: You can specify Cloudinary configuration for each image on the Image component. This can be tedious when you are dealing with multiple images. CloudinaryContext allows you to apply configuration to a group of Images.

Most times you would end up with a structure like this:

<CloudinaryContext>
    <Image>
        <Transformation />
        <Transformation />
    </Image>
    <Image>
        <Transformation />
    </Image>
</CloudinaryContext>

Back to our demo app, we can request an image from the Cloudinary server and display it with the following components:

import React, { Component } from 'react';
import axios from 'axios';
import { CloudinaryContext, Transformation, Image } from 'cloudinary-react';
import { render } from 'react-dom';

class Main extends Component {
    constructor(props) {
        super(props);
        this.state = {
            gallery: []
        }
    }
    componentDidMount() {
    // Request for images tagged xmas       
axios.get('http://res.cloudinary.com/christekh/image/list/xmas.json')
            .then(res => {
                console.log(res.data.resources);
                this.setState({gallery: res.data.resources});
            });
    }
    uploadWidget() {
       // . . .
    }
    render(){
        return (
            <div className="main">
                <h1>Galleria</h1>
                <div className="gallery">
                    <CloudinaryContext cloudName="CLOUDNAME">
                        {
                            this.state.gallery.map(data => {
                                return (
                                    <div className="responsive" key={data.public_id}>
                                        <div className="img">
                                            <a target="_blank" href={`http://res.cloudinary.com/christekh/image/upload/${data.public_id}.jpg`}>
                                                <Image publicId={data.public_id}>
                                                    <Transformation
                                                        crop="scale"
                                                        width="300"
                                                        height="200"
                                                        dpr="auto"
                                                        responsive_placeholder="blank"
                                                    />
                                                </Image>
                                            </a>
                                            <div className="desc">Created at {data.created_at}</div>
                                        </div>
                                    </div>
                                )
                            })
                        }
                    </CloudinaryContext>
                    <div className="clearfix"></div>
                </div>
            </div>

        );
    }
}

render(<Main />, document.getElementById('container'));

Take one more look at the upload code:

 cloudinary.openUploadWidget({ cloud_name: 'christekh', upload_preset: 'idcidr0h', tags:['xmas']},
            function(error, result) {
            . . .

Each image is tagged with xmas, which serves as a way to request images with this tag as a collection. This is exactly what we are using the axios library to do when the component mounts:

axios.get('http://res.cloudinary.com/CLOUDNAME/image/list/xmas.json')
            .then(res => {
                console.log(res.data.resources);
                this.setState({gallery: res.data.resources});
            });

axios uses promises, so whenever the promise resolves in our case, we have a payload of images. We take advantage of React state to update our UI with the fetched resources.

Down to rendering, we configure the CloudinaryContext with our cloud_name, iterate over the gallery state that stores the images and displays them using the Image component. We also apply few transformations using the Transformation component.

For security reasons, Cloudinary will not allow you to make such request from the client unless you tell it to. The best way to go is to use the admin API via a backend SDK and then send the resource list to the client.

Updating State with New Uploads

We are able to upload images and request for images to be displayed on the user’s browsers. Here is how we update the displayed images instantly when the user uploads a new image:

uploadWidget() {
        let _this = this;
        cloudinary.openUploadWidget({ cloud_name: 'CLOUDNAME', upload_preset: 'PRESET', tags:['xmas']},
            function(error, result) {
            // Update gallery state with newly uploaded image
                _this.setState({gallery: _this.state.gallery.concat(result)})
            });
    }

Rather than logging the uploaded image information to the console, we update the gallery state, which bears the list of requested images, by concatenating the uploaded result to the gallery.

Image Management Simplified

Image uploads, transformation and delivery has never been easier. These tasks have been a serious challenge for developers. Cloudinary has created a way to abstract all this hard work, enabling you to simply plug and play.




ma

2000 FIFA Club World Championship: Corinthians 0-0 Vasco da Gama (4-3 PSO)

Corinthians-Vasco da Gama, FIFA Club World Cup Brazil 2000 Final: The all-Brazilian final had a plethora of familiar names - including legend Romario, Edmundo, Gilberto Melo, Ricardinho and Dida - and ended in a dramatic penalty shootout.




ma

2008 Club World Cup Final: LDU Quito 0-1 Manchester United

Liga de Quito-Manchester United, FIFA Club World Cup Japan 2008 Final: Both teams showed impressive attacking flair, but it was Wayne Rooney's angled shot that made the difference.




ma

2010 Club World Cup Final: TP Mazembe 0-3 Inter

TP Mazembe-Inter Milan, FIFA Club World Cup UAE 2010: Internazionale was in rampant form as they crushed the dreams of the first African finalists.




ma

Kashima Antlers 3-2 CD Guadalajara (UAE 2018)

Losing finalists at the 2016 edition of the FIFA Club World Cup, Kashima Antlers defeated Mexico's CD Guadalajara to set up a semi-final against the team that beat them in that 2016 final, Real Madrid.




ma

Kashima Antlers 0-4 River Plate (UAE 2018)

River Plate ended their FIFA Club World Cup UAE 2018 campaign with an emphatic 4-0 victory over AFC Champions League holders Kashima Antlers.




ma

Real Madrid 4-1 Al Ain (UAE 2018)

Real Madrid capped off another memorable year by claiming a third successive FIFA Club World Cup title, defeating host team Al Ain 4-1 at Abu Dhabi's Zayed Sports City Stadium.




ma

Real Madrid CF 4-1Al Ain (UAE 2018)

Real Madrid CF beat Al Ain in a 4-1 thriller in the FIFA Club World Cup (2018) final. Watch all 5 goals from the final, including Modric's outside the box curler.




ma

The dressing room of Mali team

KOLKATA, INDIA - OCTOBER 28: The dressing room of Mali team is pictured prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

The dressing room of Mali team

KOLKATA, INDIA - OCTOBER 28: The dressing room of Mali team is pictured prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

The dressing room of Mali team

KOLKATA, INDIA - OCTOBER 28: The dressing room of Mali team is pictured prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Coach of Brazil, Carlos Amadeu arrives at the stadium

KOLKATA, INDIA - OCTOBER 28: Coach of Brazil, Carlos Amadeu arrives at the stadium prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Players of Mali enter to the field

KOLKATA, INDIA - OCTOBER 28: Players of Mali enter to the field prior the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Players from Mali enter the field

KOLKATA, INDIA - OCTOBER 28: Players from Mali enter the field prior the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

: A player from Mali prays before entering the field

KOLKATA, INDIA - OCTOBER 28: A player from Mali prays before entering the field prior the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Fans arrive ahead of the FIFA U-17 World Cup India 2017 Final match

KOLKATA, INDIA - OCTOBER 28: Fans arrive ahead of the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




ma

Fans arrive ahead of the FIFA U-17 World Cup India 2017 Final match

KOLKATA, INDIA - OCTOBER 28: Fans arrive ahead of the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




ma

The dressing room of Mali team is pictured

KOLKATA, INDIA - OCTOBER 28: The dressing room of Mali team is pictured prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Fans arrive ahead of the FIFA U-17 World Cup India 2017 Final match

KOLKATA, INDIA - OCTOBER 28: Fans arrive ahead of the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




ma

The Mali team is pictured prior to the FIFA U-17 World Cup India 2017 3rd Place match

KOLKATA, INDIA - OCTOBER 28: The Mali team is pictured prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Players Mali warm up

KOLKATA, INDIA - OCTOBER 28: Players Mali warm up prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Players Mali warm up

KOLKATA, INDIA - OCTOBER 28: Players Mali warm up prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Coach of Brazil, Carlos Amadeu arrives at the stadium

KOLKATA, INDIA - OCTOBER 28: (EDITOR'S NOTE: This image has been processed using digital filters). Coach of Brazil, Carlos Amadeu arrives at the stadium prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Coach of Mali, Jonas Komla arrives at the stadium

KOLKATA, INDIA - OCTOBER 28: (EDITOR'S NOTE: This image has been processed using digital filters). Coach of Mali, Jonas Komla arrives at the stadium prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Coach of Mali, Jonas Komla arrives at the stadium

KOLKATA, INDIA - OCTOBER 28: Coach of Mali, Jonas Komla arrives at the stadium prior to the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Players of Brazil and Mali enter to the field

KOLKATA, INDIA - OCTOBER 28: Players of Brazil and Mali enter to the field prior the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Players of Brazil and Mali enter to the field

KOLKATA, INDIA - OCTOBER 28: Players of Brazil and Mali enter to the field prior the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Players of Brazil and Mali line up for the National Anthems

KOLKATA, INDIA - OCTOBER 28: Players of Brazil and Mali line up for the National Anthems ahead of the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Players of Brazil and Mali enter to the field

KOLKATA, INDIA - OCTOBER 28: Players of Brazil and Mali enter to the field prior the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Lincoln (R) of Brazil battles for the ball with Ibrahim Kane and Boubacar Haidara of Mali

KOLKATA, INDIA - OCTOBER 28: Lincoln (R) of Brazil battles for the ball with Ibrahim Kane and Boubacar Haidara of Mali during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Players of Mali line up for a picture

KOLKATA, INDIA - OCTOBER 28: Players of Mali line up for a picture during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Paulinho of Brazil battles for the ball with Hadji Drame of Mali

KOLKATA, INDIA - OCTOBER 28: Paulinho of Brazil battles for the ball with Hadji Drame of Mali during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Paulinho of Brazil and Fode Konate of Mali in action

KOLKATA, INDIA - OCTOBER 28: Paulinho of Brazil and Fode Konate of Mali in action during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




ma

Lincoln of Brazil battles for the ball with Boubacar Haidara and Mamadi Fofana of Mali

KOLKATA, INDIA - OCTOBER 28: Lincoln (R) of Brazil battles for the ball with Boubacar Haidara and Mamadi Fofana of Mali during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Lincoln of Brazil battles for the ball with Boubacar Haidara and Mamadi Fofana of Mali

KOLKATA, INDIA - OCTOBER 28: Lincoln (R) of Brazil battles for the ball with Boubacar Haidara and Mamadi Fofana of Mali during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Paulinho of Brazil battles for the ball with Fode Konate of Mali

KOLKATA, INDIA - OCTOBER 28: Paulinho (R) of Brazil battles for the ball with Fode Konate of Mali during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




ma

Paulinho of Brazil battles for the ball with goalkeeper Youssouf Koita of Mali

KOLKATA, INDIA - OCTOBER 28: Paulinho (C) of Brazil battles for the ball with goalkeeper Youssouf Koita of Mali during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)