I love to teach, even though I am no expert. I learn every day and I have the fortune to have great mentors. After all not everyone has the opportunity to learn from mentors and peers. The book is my attempt to give something back which might help people to get started and advance in React.
The following article includes the first chapters of an eBook to learn React. In the future it highly depends on your feedback and contribution. I try my best to teach in the best way possible, but I can only improve with your help. I am keen to hear your honest thoughts on Twitter.
But why me? In the past I have written a larger tutorial to implement a SoundCloud Client in React + Redux. I never expected the overwhelming reaction. I learned a lot during the process of writing. But even more by getting your honest feedback. It was my first attempt to teach people in programming.
It also taught me to do better. I realized the SoundCloud tutorial is suited for advanced developers. It uses several tools to bootstrap your application and dives pretty quickly into Redux. Still it helped a lot of people to get started. In my opinion it’s a great tutorial to get a bigger picture of React + Redux. I use every free minute to improve the material, but it’s time consuming. I am going to overhaul it as a whole in the future.
The Road to learn React
Build a Hacker News Client to learn React. No setup configuration. No tooling. No Redux. Plain React in 90 pages of learning material.
Get the BookIn the Road to learn React I want to offer a foundation before you start to dive into the more advanced React ecosystem. It has less tooling and less external state management, but more React. It explains general concepts and patterns. Additionally it links to the official documentation, because it’s a great reference to learn React. After all I want to give a clear road to learn the React ecosystem. It should provide you a solid foundation before you dive into more advanced topics like Redux.
How do I get updates? You can subscribe or follow me on Twitter for updates. It keeps me motivated to work on the book as well. Once you have a copy of the book from Leanpub, the book will stay updated.
Does it cover Redux? So far it doesn’t. The book should give you a solid foundation before you dive into advanced topics like Redux. Still the implementation in the book will show you that you don’t need Redux to build a presentable application.
But why is the book for free? I have put a lot of effort into this and will do so in the future. My desire is to reach as many people as possible. Everyone should be enabled to learn React independent of background. Still you can decide to pay something, if you can effort it. It’s pay what you want in the end. Once you have your version of the book, you will automatically get all the updates. I would appreciate each of your social shares for the book.
Does the article cover all book chapters? No. At this time the blog post covers 2 of 5 chapters. Grab your book on Leanpub to get all chapters. It has over 100 pages of learning material.
Will you add more chapters in the future? It depends on the community. If there is an acceptance for the book, I will deliver more chapters. Additionally I would love to hear your thoughts about possible chapters to improve and enrich the learning experience.
- well rounded real world Hacker News client in React
- no complicated configurations
- create-react-app to bootstrap your application
- efficient lightweight code
- only React setState as state management (so far...)
- JavaScript ES6 along the way
- the React API with setState and lifecycle methods
- a real world API (Hacker News)
- advanced interactions
- client-sided sorting
- client-sided filtering
- server-sided searching
- client-side caching
- higher order functions and higher order components
- snapshot test components with Jest
- unit test components with Enzyme
- neat libraries along the way
- exercises and more readings along the way
- internalize and reinforce your learnings
- deploy your app to production
- advanced components and interactions to build a powerful dashboard
- give your app a structure in terms of files/folders
- arrive at the point to experience how state management could help you
- introduce a state management library to your app
- use common patterns in React and state management
- get to know open source style guides for a better code style
- more neat libraries along the way
- usage of React dev tools and performance profiling
- get to know a diverse set of styling tools in React
- animate your components
In general each chapter will build up on the previous. Each of them will dive into a new learning. Don’t rush through the book. You should internalize each step. You could apply your own implementations and read more about the topic. Make yourself comfortable with the learnings before you continue.
After you have read the book you could dive into the SoundCloud Client in React + Redux. It guides you to implement your own SoundCloud application with a state management library.
I would like to hear your thoughts on Twitter.
- Bootstrap your React App
- Basics in React
- Getting Real with an API
- Lifecycle Methods
- Fetch Data
- Client- or Server-side Interaction: Search
- Paginated Fetch
- Client Cache
- Advanced React Components
- Snapshot Tests with Jest
- Unit Tests with Enzyme
- Loading …
- Higher Order Component
- Advanced Sorting
Lift the State- Going Live!
The chapter will give you an introduction to React. It clarifies why you should learn React in the first place. Once that’s clarified you will bootstrap your first React app. Along the way you will get an introduction to JSX to be prepared for your first React components.
Why should you bother to learn React? In the recent years single page applications (SPA) got popular. Frameworks like Angular, Ember and Backbone helped JavaScript people to build modern web applications beyond jQuery. The list is not exhaustive. There exists a wide range of SPA frameworks. When you consider the release dates, most of them are among the first generation of SPAs: Angular 2010, Backbone 2010, Ember 2011.
The initial React release was 2013 by Facebook. React is no SPA framework but a view library. You can get easily started to render your first components in a browser. But the whole ecosystem around React makes it possible to build single page applications.
But why should you consider to use React over the first generation of SPA frameworks? While the first generation of SPAs tried to solve a lot of things at once, React only helps you to build your view layer. It’s a library and not a whole framework. The idea behind it: Your view is a hierarchy of composable components.
In React you can focus on your view before you introduce more aspects to your application. Every other aspect is another building block for your SPA. These building blocks are essential.
First you can learn them step by step without worrying to understand everything at once. It’s different in comparison to a framework which gives you every building block from the start.
Second all building blocks are interchangeable. It makes the ecosystem around React such an innovative place. Multiple solutions are competing witch each other. You can pick the most appealing solution for you and your use case.
The first generation SPA frameworks arrived at an enterprise level. React stays innovative and gets adapted by multiple tech thought leader companies like Airbnb, Netflix and of course Facebook. React is probably one of the best choices for building UI nowadays. It has a good design, an amazing ecosystem and a great community. Everyone is keen to experience where it will lead us in 2017.
Before you start to read the book, you should be quite familiar with HTML, CSS and JavaScript (ES5). Additionally you will need a working editor and terminal. Last but not least you will need an installation of node and npm.
These are my versions of node and npm at the time of writing the book.
node--version*v5.0.0npm--version*v3.3.6
You will use create-react-app to bootstrap your app. It’s an opinionated but zero-configuration starter kit for React introduced by Facebook. People like and would recommend it to starters by 96%. In create-react-app the tools evolve in the background while the focus is on the application implementation.
To get started you will have to install the package to your global packages on your command line. You should already have npm installed to install the package.
npminstall-gcreate-react-app
Now you can bootstrap your first app and navigate into the directory:
create-react-apphackernewscdhackernews
When you open the app in your editor, you will find the following folder structure:
hackernews/README.mdnode_modules/package.json.gitignorepublic/favicon.icoindex.htmlsrc/App.cssApp.jsApp.test.jsindex.cssindex.jslogo.svg
In the beginning everything you need is located in the src folder. The main focus lies on the App.js file to implement React components. But there is also the App.test.js for tests and the index.js as entry point to the React world. We will get to know them in a later chapter.
Additionally create-react-app comes with the following npm scripts for your command line:
// Runs the app in http://localhost:3000npmstart// Runs the testsnpmtest// Builds the app for productionnpmrunbuild
You can read more about the scripts and create-react-app in general.
Exercises:
npm start
your app and visit the page in your browser- run the interactive
npm test
script - make yourself familiar with the folder structure
Now you will get to know JSX. Let’s dive into the source code provided by create-react-app. The only file you will touch in the beginning will be the src/App.js.
importReact,{Component}from'react';importlogofrom'./logo.svg';import'./App.css';classAppextendsComponent{render(){return(<divclassName="App"><divclassName="App-header"><imgsrc={logo}className="App-logo"alt="logo"/><h2>WelcometoReact</h2></div><pclassName="App-intro">Togetstarted,edit<code>src/App.js</code> and save to reload.</p></div>);}}exportdefaultApp;
create-react-app already scaffolded a boilerplate application. In the file you have an ES6 class component with the name App. Basically you can use the <App />
component everywhere in your application now. Once you use it, it will produce an instance of your component. The elements it returns are specified in the render()
function.
Pretty soon you will see where the App component is used. Otherwise you wouldn’t see the rendered output in the browser, would you?
The content in the render block looks pretty similar to HTML, but it’s JSX. JSX allows you to mix HTML and JavaScript. It’s powerful yet confusing in the beginning when you are used to plain HTML. That’s why a good starting point is to use basic HTML in your JSX. Next you can start to embed JavaScript expressions in between by using curly braces.
Try it. Define a property and use it in JSX.
importReact,{Component}from'react';importlogofrom'./logo.svg';import'./App.css';classAppextendsComponent{render(){consthelloWorld='Welcome to React';return(<divclassName="App"><divclassName="App-header"><imgsrc={logo}className="App-logo"alt="logo"/><h2>{helloWorld}</h2></div><pclassName="App-intro">Togetstarted,edit<code>src/App.js</code> and save to reload.</p></div>);}}exportdefaultApp;
Additionally you might have noticed the className
attribute. Because of technical reasons JSX had to replace HTML attributes like class (className) and for (htmlFor).
ES6 Sugar:
In ES5 you declare variables with var. In ES6 there are two more variable declarations: const and let.
Exercises:
Before you continue with the App component, you might want to see where it’s used. It’s located in your entry point to the React world src/index.js.
importReactfrom'react';importReactDOMfrom'react-dom';importAppfrom'./App';import'./index.css';ReactDOM.render(<App/>,document.getElementById('root'));
Basically ReactDOM.render uses a DOM node in your html to replace it with your React components. That’s how you can easily integrate React in every app.
ReactDOM.render expects two arguments.
The first argument is JSX. It already takes your App component, but you don’t need to pass a component. It would be sufficient to use <div>Hello React World</div>
. After all the first argument is the content to be rendered.
The second argument specifies the place where the React application hooks into your HTML. It expects an element with an id="root"
. Open your public/index.html file to find the id.
Exercises:
Let’s get back to your App component. So far your rendered some random properties in your JSX. Now you will start to render a list of items. The list will be some mock data in the beginning, but later you will fetch the data from an external API. That will be far more exciting.
Since you can use JavaSript in JSX, it’s possible to map over your data to display each item.
importReact,{Component}from'react';import'./App.css';constlist=[{title:'React',url:'https://facebook.github.io/react/',author:'Jordan Walke',num_comments:3,points:4,objectID:0,},{title:'Redux',url:'https://github.com/reactjs/redux',author:'Dan Abramov, Andrew Clark',num_comments:2,points:5,objectID:1,},];classAppextendsComponent{render(){return(<divclassName="App">{list.map(function(item){return(<div><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>);})}</div>);}}exportdefaultApp;
Additionally you have to assign a key property to each list element. Only that way React is able to identify added, changed and removed items.
{list.map(function(item){return(<divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>);})}
Give your elements a stable id. Don’t make the mistake to use the array key which isn’t stable. React will have a hard time to identify the items properly when the order of them changes.
// bad example{list.map(function(item,key){return(<divkey={key}>...</div>);})}
Now when you open your app in a browser both list items should get rendered and be visible.
ES6 Sugar:
Let’s have a look again at the map function. It takes a function itself, which you can write more concise in ES6.
First you can use the arrow function.
{list.map((item)=>{return(<divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>);})}
Second you can remove the block body and thus remove the return statement. In a concise body an implicit return is attached.
{list.map((item)=><divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}
Now your JSX looks more readable again.
Exercises:
Your src/App.js should look like the following by now:
importReact,{Component}from'react';import'./App.css';constlist=[{title:'React',url:'https://facebook.github.io/react/',author:'Jordan Walke',num_comments:3,points:4,objectID:0,},{title:'Redux',url:'https://github.com/reactjs/redux',author:'Dan Abramov, Andrew Clark',num_comments:2,points:5,objectID:1,},];classAppextendsComponent{render(){return(<divclassName="App">{list.map((item)=><divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}</div>);}}exportdefaultApp;
You have learned to bootstrap your own React app! Let’s recap the last chapters:
- React
- create-react-app bootstraps a React app
- JSX mixes up HTML and JavaScript to express React components
- ReactDOM.render() is an entry point for a React app
- built-in JavaScript functionalities like map can be used render a list of items
- ES6
- more variable declarations with const and let
- arrow functions with block and concise bodies to shorten your function declarations
It makes sense to make a break at this point. Internalize the learnings and apply them on your own. You can experiment with the source code you have written so far.
The chapter will focus on the basics in React. You will learn to manage internal component state, to implement component interactions and to compose components. Moreover it will show you to declare components in different ways.
Internal component state allows you to store, modify and delete properties of your components. Let’s introduce a class constructor where you can set the initial internal component state.
classAppextendsComponent{constructor(props){super(props);this.state={list:list,};}...}
In your case the initial state is the list of items.
Notice that you have to call super(props);
to call the constructor of the parent class. It’s mandatory.
classAppextendsComponent{...render(){return(<divclassName="App">{this.state.list.map((item)=><divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}</div>);}}
In the render function you have access to the component internal state by using this
. As before you can map over the list of items.
ES6 Sugar:
You can use a shorthand syntax to initialize properties in an object. In your case it makes sense because the property and variable share the same name.
// instead ofthis.state={list:list};// you can usethis.state={list};
Exercises:
Now you have some static internal state in your component. But you don’t manipulate the internal state so far. The best to experience state manipulation is by implementing a component interaction. It could be a search field. The input of the search field should be used to filter your list.
First you define your input field in your JSX.
classAppextendsComponent{...render(){return(<divclassName="App"><form><inputtype="text"/></form>{this.state.list.map((item)=><divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}</div>);}}
In the following scenario you will type into the field and filter the list by the search term. To be able to filter the list, you need the value of the input field. But where to access the value? Naturally in React the value goes into the internal component state to be accessible und updatable.
Let’s define a callback function for the input field which manipulates the internal component state.
classAppextendsComponent{...render(){return(<divclassName="App"><form><inputtype="text"onChange={this.onSearchChange}/></form>...</div>);}}
The callback function is bound to the component and thus a component method. You have to bind and define the method.
classAppextendsComponent{constructor(props){super(props);this.state={list,};this.onSearchChange=this.onSearchChange.bind(this);}onSearchChange(event){...}render(){...}}
The callback gives you access to the input field event. The event has the value of the input field in its target object. By using this.setState
you can manipulate the internal component state. Additionally you should define the initial state for the query.
classAppextendsComponent{constructor(props){super(props);this.state={list,query:'',};this.onSearchChange=this.onSearchChange.bind(this);}onSearchChange(event){this.setState({query:event.target.value});}render(){...}}
Now you store the value to your component state every time the value in the input field changes. But one piece is missing.
In React applications you will strictly follow an unidirectional data flow. The input field already updated the internal component state, but to finish the roundtrip you have to update the value of the input field with the internal state too.
You have to retrieve the query property from the internal component state and set it as value in the input field.
classAppextendsComponent{...render(){constquery=this.state.query;return(<divclassName="App"><form><inputtype="text"value={query}onChange={this.onSearchChange}/></form>...</div>);}}
The unidirectional data flow roundtrip finished. Now the input field value is under your control.
The whole internal state management and unidirectional data flow might be new to you. But once you are used to it, it will be your natural flow to implement things in React. So what’s next? You save your input value as query, but what about searching the list?
Before you map the list you can filter it.
classAppextendsComponent{...render(){constquery=this.state.query;return(<divclassName="App"><form><inputtype="text"value={query}onChange={this.onSearchChange}/></form>{this.state.list.filter(isSearched(query)).map((item)=><divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}</div>);}}
The filter
function takes a function to evaluate each item in the list. If the evaluation for an item is true, the item stays in the list.
But now you need to pass the query property to your evaluation process. That’s why you can use a higher order function, which takes the query but returns another function. The returned function will do the evaluation for each item, but has access to the query property.
functionisSearched(query){returnfunction(item){return!query||item.title.toLowerCase().indexOf(query.toLowerCase())!==-1;}}classAppextendsComponent{...}
You filter the list only when a query is set. When a query is set, you match the incoming query pattern with the title of the item. Only when the pattern matches you return true. Don’t forget to lower case everything, otherwise there will be mismatches between a query ‘redux’ and a item title ‘Redux’.
The search field should do its work now. Try it.
ES6 Sugar:
You can even add some more ES6 syntax again. First you can destructure objects and arrays. Try it by destructuring the internal component state.
render(){const{query,list}=this.state;return(<divclassName="App"><form><inputtype="text"value={query}onChange={this.onSearchChange}/></form>{list.filter(isSearched(query)).map((item)=><divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}</div>);
Second you can make the function more concise in ES6 by using arrow functions again.
You can refactor your higher order function:
// beforefunctionisSearched(query){returnfunction(item){return!query||item.title.toLowerCase().indexOf(query.toLowerCase())!==-1;}}// afterconstisSearched=(query)=>(item)=>!query||item.title.toLowerCase().indexOf(query.toLowerCase())!==-1;
One could argue which one is more readable. Personally I prefer the second one.
The React ecosystem uses a lot of functional programming concepts. It happens quite often that you will use a function which returns a function. These are called higher order functions. In ES6 you can express these more concise with arrow functions.
Exercises:
So far you have one large App component. Let’s start to split it up into smaller composable components. You can define a component for the search input and a component for the list items.
classAppextendsComponent{...render(){const{query,list}=this.state;return(<divclassName="App"><Searchvalue={query}onChange={this.onSearchChange}/><Tablelist={list}pattern={query}/></div>);}}classSearchextendsComponent{render(){const{value,onChange}=this.props;return(<form><inputtype="text"value={value}onChange={onChange}/></form>);}}classTableextendsComponent{render(){const{list,pattern}=this.props;return(<div>{list.filter(isSearched(pattern)).map((item)=><divkey={item.objectID}><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}</div>);}}
Properties, they are called props in React, can be passed to components. The components themselves have every property accessible in the props
object.
Now you have three ES6 class components.
Still you can’t compose components into each other. That’s why there exists the React children property. You can try the following to see the children property in action.
classAppextendsComponent{...render(){const{query,list}=this.state;return(<divclassName="App"><Searchvalue={query}onChange={this.onSearchChange}>Search</Search><Tablelist={list}pattern={query}/></div>);}}classSearchextendsComponent{render(){const{value,onChange,children}=this.props;return(<form>{children}<inputtype="text"value={value}onChange={onChange}/></form>);}...}
The children property should get rendered in the Search component now.
By using the children property you can compose components into each other. You can pass whole components and component hierarchies as children.
Exercises:
Now you have three ES6 class components. But you can do better by using functional stateless components. Before you will refactor your components to functional stateless components, let me explain the different types of component declarations.
Functional stateless components are functions which get an input and return an output. The output is a component instance. There are no side effects (functional) and they have no internal state (stateless). You cannot access the state with this.state
because there is no this
object. Additionally they have no lifecycle methods. You didn’t learn about lifecycle methods yet, but you already used two: constructor()
and render()
. Keep this in mind, when you arrive at the lifecycle methods chapter later on.
Besides of the functional stateless component, you already know the ES6 class component with the this
object and two lifecycle methods.
Additionally there is a third type of component declaration: React.createClass. It was used in older versions of React, but is declared as deprecated now. I still wanted to mention it, in case you come across these declarations in older React material.
But when to use functional stateless components and ES6 class components? A good rule of thumb is to use functional stateless components when you don’t need internal component state nor component lifecycle methods. Usually you start to implement your components as functional stateless components. Once you need access to the state or lifecycle methods, you will refactor it to an ES6 class component.
The App component uses internal state. That’s why it has to stay as ES6 class component. But both of your new components are stateless without lifecycle methods. Let’s refactor the Search component together to a stateless functional component. The Table component refactoring will remain as your exercise.
functionSearch(props){const{value,onChange,children}=props;return(<form>{children}<inputtype="text"value={value}onChange={onChange}/></form>);}
You already know and can apply the props destructuring. The best practice is use it in the function signature in the first place.
functionSearch({value,onChange,children}){return(<form>{children}<inputtype="text"value={value}onChange={onChange}/></form>);}
But it can get better. You know that arrow functions allow you to keep your functions concise. Since your functional stateless component is a function, you can keep it concise as well.
constSearch=({value,onChange,children})=><form>{children}<inputtype="text"value={value}onChange={onChange}/></form>
The last step is especially useful to enforce only to have props as input and an element as output. Nothing in between. Still you could do something in between by using a block body.
constSearch=({value,onChange,children})=>{// do somethingreturn(<form>{children}<inputtype="text"value={value}onChange={onChange}/></form>);}
Now you have one lightweight functional stateless component. Once you would need access to its internal component state or lifecycle methods you would refactor it to an ES6 class component.
Exercises:
Let’s add some basic styling to your app and components. You can reuse the src/App.css and src/index.css files. I prepared some CSS, but feel free to use your own style. If you don’t come up with your own style, copy and paste the following styles.
src/index.css
body{color:#222;background:#f4f4f4;font:40014pxCoreSans,Arial,sans-serif;}a{color:#222;}a:hover{text-decoration:underline;}ul,li{list-style:none;padding:0;margin:0;}input{padding:10px;border-radius:5px;outline:none;margin-right:10px;border:1pxsolid#dddddd;}button{padding:10px;border-radius:5px;border:1pxsolid#dddddd;background:transparent;color:#808080;cursor:pointer;}button:hover{color:#222;}*:focus{outline:none;}
src/App.css
.page{margin:20px;}.interactions{text-align:center;}.table{margin:20px0;}.table-header{display:flex;line-height:24px;font-size:16px;padding:010px;justify-content:space-between;text-transform:uppercase;}.table-empty{margin:200px;text-align:center;font-size:16px;}.table-row{display:flex;line-height:24px;white-space:nowrap;margin:10px0;padding:10px;background:#ffffff;border:1pxsolid#e3e3e3;}.table-header>span{overflow:hidden;text-overflow:ellipsis;padding:05px;}.table-row>span{overflow:hidden;text-overflow:ellipsis;padding:05px;}.button-inline{border-width:0;background:transparent;color:inherit;text-align:inherit;-webkit-font-smoothing:inherit;padding:0;font-size:inherit;cursor:pointer;}.button-active{border-radius:0;border-bottom:1pxsolid#38BB6C;}
Now you can use the style in your components. Don’t forget to use React className.
classAppextendsComponent{...render(){const{query,list}=this.state;return(<divclassName="page"><divclassName="interactions"><Searchvalue={query}onChange={this.onSearchChange}>Search</Search></div><Tablelist={list}pattern={query}/></div>);}}constSearch=({value,onChange,children})=><form>{children}<inputtype="text"value={value}onChange={onChange}/></form>constTable=({list,pattern})=><divclassName="table">{list.filter(isSearched(pattern)).map((item)=><divkey={item.objectID}className="table-row"><span><ahref={item.url}>{item.title}</a></span><span>{item.author}</span><span>{item.num_comments}</span><span>{item.points}</span></div>)}</div>
Another technique in React to style components is inline style. You can pass style objects to your components. Let’s keep the Table column width flexible by using inline style.
constTable=({list,pattern})=><divclassName="table">{list.filter(isSearched(pattern)).map((item)=><divkey={item.objectID}className="table-row"><spanstyle={{width:'40%'}}><ahref={item.url}>{item.title}</a></span><spanstyle={{width:'30%'}}>{item.author}</span><spanstyle={{width:'15%'}}>{item.num_comments}</span><spanstyle={{width:'15%'}}>{item.points}</span></div>)}</div>
It’s really inlined now. You could define the style objects outside as well.
constlargeColumn={width:'40%',};constmidColumn={width:'30%',};constsmallColumn={width:'15%',};
After that you could use it in your columns <span style={smallColumn}>
.
In general you will find different opinions and solutions for style in React. I don’t want to be opinionated here, but I leave you some options to read about it. I’m open to your thoughts about other options as well.
The chapter might get overhauled in the future to give you an opinionated approach.
Your src/App.js should look like the following by now:
importReact,{Component}from'react';import'./App.css';constlist=[{title:'React',url:'https://facebook.github.io/react/',author:'Jordan Walke',num_comments:3,points:4,objectID:0,},{title:'Redux',url:'https://github.com/reactjs/redux',author:'Dan Abramov, Andrew Clark',num_comments:2,points:5,objectID:1,},];constisSearched=(query)=>(item)=>!query||item.title.toLowerCase().indexOf(query.toLowerCase())!==-1;classAppextendsComponent{constructor(props){super(props);this.state={list,query:'',};this.onSearchChange=this.onSearchChange.bind(this);}onSearchChange(event){this.setState({query:event.target.value});}render(){const{query,list}=this.state;return(<divclassName="page"><divclassName="interactions"><Searchvalue={query}onChange={this.onSearchChange}>Search</Search></div><Tablelist={list}pattern={query}/></div>);}}constSearch=({value,onChange,children})=><form>{children}<inputtype="text"value={value}onChange={onChange}/></form>constTable=({list,pattern})=><divclassName="table">{list.filter(isSearched(pattern)).map((item)=><divkey={item.objectID}className="table-row"><spanstyle={{width:'40%'}}><ahref={item.url}>{item.title}</a></span><spanstyle={{width:'30%'}}>{item.author}</span><spanstyle={{width:'15%'}}>{item.num_comments}</span><spanstyle={{width:'15%'}}>{item.points}</span></div>)}</div>exportdefaultApp;
You have learned the basics to write your own React app! Let’s recap the last chapters:
- React
- this.state and setState to manage your internal component state
- forms and events in React
- compose components with children
- usage and implementation of ES6 class components and functional stateless components
- approaches to style your components
- ES6
- destructuring of objects and arrays
- arrow functions with concise and block body
- General
Again it makes sense to make a break. Internalize the learnings and apply them on your own. You can experiment with the source code you have written so far. Additionally you could read more in the official documentation.
That’s the last chapter of the book preview. You can read more chapters on Leanpub! Grab it and pay as what want. I want to enable everyone to learn React. You can have a look again at the Table of Contents to see what you can expect to find on Leanpub.
I hope you liked it so far! When you get the book on Leanpub, in the FAQ you will get insights on how you could contribute. I would really appreciate your support on social media to reach as many people as possible to grab a version of the book.
I would like to hear your thoughts. Find me on Twitter and GitHub
If you liked the content, share it with your people and subscribe for updates.
The Road to learn React
Build a Hacker News Client to learn React. No setup configuration. No tooling. No Redux. Plain React in 90 pages of learning material.
Get the Book