React + GraphQL = ❤
This is the👌 third article from the series “Build a Pokédex with GraphQL, React.js, Semaphore CI, Heroku and Docker”.
A quick recap from our previous chapters:
- we built a GraphQL Server
- we fetched data from PokéApi
- we defined schemas
- we interacted via GraphiQL
- we wrote unit tests
- we wrote integration tests
If you haven’t read the previous chapter I will put the link below, so you can give it a look 👀.
This is the ✌️ second article from the series “Build a Pokédex with GraphQL, React.js, Semaphore CI, Heroku and Docker…medium.com
We use Webpack as build tool. Its main goal is to group all our client’s application files to process and produce a build file. Webpack allows us to easily managing our assets, (optimization of images, css file concatenation, minification…).
npm i --save-dev webpack
We use Webpack version 2 which brings variety of anticipated features, including native support for ES6 modules. Using of imports and exports makes possible tree-shaking optimization. “Tree-shaking is the ability to only include code in your bundle that is being used.”
“If you wonder why it’s called tree-shaking: think of your application as a dependency graph, this is a tree, and each export is a branch. So if you shake the tree, the dead branches will fall.” — Roman Liutikov
Learn more, with this article .
Webpack 2 was just released from beta last week. It brings with it a variety of anticipated features, including native…medium.freecodecamp.com
Here the webpack.config.js
We define an entry and an output file, the bundle is required by the index.html.
babel-loader is a Webpack loader, it parses all
jsx files with babel. We configure babel with babelrc file.
Create a .babelrc in project’s root.
We configure babel to transpile
js, and using last es2015 features !
Then install all babel dependencies:
npm i babel-core babel-loader babel-preset-es2015-native-modules babel-register --save-dev
- babel-core : Babel itself
- babel-preset-es2015-native-modules : Babel preset for all es2015 plugins except babel-plugin-transform-es2015-modules-commonjs
It remains some Webpack configuration, but we have to add some code.
Create an app folder and the react root file app.jsx.
mkdir app && cd app
npm i --save-dev react react-dom
React-dom package makes a React element into the DOM in the supplied container. Here the container is a DOM element with the ‘app’ id.
index.html with an app id. The template require the
bundle.js generated by Webpack.
Copy-paste this content:
index.html file should be moved in
dist folder. We can use a plugin to copy this file to the
dist folder. But we can be clever here. Thanks to the plugin html-webpack-plugin, the
index.html should be moved in
dist folder and the script automatically required, then we can pass an hash options to enable cache busting ! That plugin adds a query parameter to the dist file name, it’s different for each builds, thus browser see that the bundle has change.
npm i --save-dev html-webpack-plugin
Then add a plugins property to Webpack’s configuration with that code:
Don’t forget to require html-webpack-plugin. Now we can remove the require for the bundle.js, it’s useless now.
Pokedex.jsx is the main entrypoint of our React App, let’s create a first version.
mkdir app/components && cd app/components
Now we have to start Webpack and the node server.
If you run
npm run watch, the server will not be launched. This is because Webpack is in watch mode. The solution that I found it’s to run concurrently both commands, thus, each command can be launched. I’ve found concurrently module. If you have a better solution, please tell me in comments.
npm i --save concurrently
Here the final package.json
The last step is to create a middleware in
index.js to serve our static resources.
npm run watch
And browse http://localhost:3001 ! You should see a beautiful Hello World !
The Webpack part is over, we can start to code !
Pokedex.jsx has responsibility to fetch Pokémons and manage actions happening from arrows.
Create 3 void methods forming your skeleton of Pokedex.jsx:
- makeRequest : Take a Pokémon id and call the GraphQL server
- arrowRight : Call makeRequest with an incremented id
- arrowLeft : Call makeRequest with a decremented id
Create two buttons which bind arrowRight and arrowLeft. Implement each method.
Here a solution :
We bind this on arrowRight and arrowLeft methods into constructor because they are used in render. To keep the current index, we save it in state.
This code closes of the final solution. We have to update makeRequest to fetch Pokémon and finally add some static components.
Communicate with you GraphQL API
Create a client folder and a getPokemon.js file.
mkdir client && cd client
In this file we call our GraphQL server to fetch a Pokémon, it sends that request to grab a Pokemon :
We create a getPokemon method taking Pokémon id, building the url, and return the request.
I’ve choose superagent because it’s isomorphic, light and easy ! Now we can update Pokedex.jsx.
We have only one function so I’ve used export default.
If you click on the right button you should receive a object, with a body property containing :
Hourra ! 🎉🎉
The heart is now over, but it’s still very ugly.
Download this image and save it in a img folder. Rename that image in Pokedex.png.
The main screen display the Pokémon sprite, the second its name and in right bottom corner its id. We browse Pokémons with arrows left and right.
A concrete example :
There is not many css. So I decided to test style in component. I recommend you to see the presentation given by Christopher Chedeau, React: CSS in JS.
Radium is a set of tools to manage inline styles on React elements. It gives you powerful styling capabilities without CSS.
npm install --save radium
Radium support pseudo-class, media query, modifiers contrary to style inline. In addition CSS in JS gives us :
- Scoped styles without selectors
- Dead code elimination
- Highly expressive
Set up Radium is not very hard, just export a Radium instance wrapping your class.
Write your style in an object, and access property in`style`tag. Example with the Pokédex image save previously:
Make img directory public:
Paddle : Left and Right buttons
Display the Pokémon order.
Display the Pokémon name
Display the Pokémon sprite.
All components are writen, we have to compose them in the main class.
We have seen how making a front-end with React.js, using a build tool with Webpack and coupled with a GraphQL API. 🤙
I hope it wasn’t too hard, and I hope to see you on my next episodes ! The code is available on branch Chapter3 of Github.
Please tell me, if you see something to improve ! 🕵️