└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # React in 1000 words 2 | 3 | The goal of this guide is to be able to familiarize with ReactJS. 4 | 5 | You'd probably have a better time here by being already familiar with 6 | JS and ES6, but I wrote this to be easily digested by anyone 7 | who has a bit of programming background. 8 | 9 | ## Intro 10 | 11 | **React is a library for building user interfaces**: think of 12 | it as an easy way to build a view with clicks and interactions. 13 | 14 | The core of React starts with components, which are plain classes: 15 | 16 | ``` jsx 17 | class LoginForm extends React.Component { 18 | render() { 19 | return ( 20 |
21 | 22 | 23 | 24 |
25 | ) 26 | } 27 | } 28 | ``` 29 | 30 | When React runs, it will look for a `render` method in your component and 31 | lay the HTML out based on what tags are returned by the method: in this case, 32 | we're going to be creating a form with 2 text inputs and a submit button. 33 | 34 | ## Interactions 35 | 36 | In order to add some interaction to our component, we need to introduce 37 | a concept called **state**: React components have some state that's used 38 | to keep track of what's happening in the UI. 39 | 40 | Let's add some silly validation on our login form, by making 41 | sure the user enters a password longer than 5 characters. To do so, React 42 | asks us to initialize our component with some initial state: 43 | 44 | ``` jsx 45 | class LoginForm extends React.Component { 46 | constructor(props) { 47 | super(props) 48 | 49 | this.state = { 50 | password: '' 51 | } 52 | } 53 | 54 | ... 55 | } 56 | ``` 57 | 58 | Now, don't worry about understanding what those `props` are -- we'll get back at 59 | them later on. For now the most important thing is to know that if we want to 60 | manage state in our component we should initialize a `state` property in the 61 | component's constructor and assign values there. 62 | 63 | If we want to change the state, we can use `this.setState({...})` and React will 64 | patch the existing state: 65 | 66 | ``` jsx 67 | class LoginForm extends React.Component { 68 | constructor(props) { 69 | super(props) 70 | 71 | this.state = { 72 | password: '' 73 | } 74 | } 75 | 76 | render() { 77 | return ( 78 |
79 | 80 | this.setState({password: e.target.value})} /> 81 | 82 |
83 | ) 84 | } 85 | } 86 | ``` 87 | 88 | As you see, we're now binding the value of the password field to `this.state.password` 89 | and, whenever the user types on the input, we update the state. 90 | 91 | When the state changes, React is smart enough to call the `render` method again, 92 | thus updating the UI (try typing in [this fiddle](https://jsfiddle.net/rbvrkhxz/)). 93 | This is a very important concept in React: **when state 94 | changes, the component re-renders**. 95 | 96 | Note you can't just do `this.state.password = e.target.value`, 97 | as React forces you to use the `setState` method so that it can "see" that the 98 | state has changed: if you were to update the state directly, React would have 99 | no visibility on the change. 100 | 101 | Let's "finalize" our example by handling the submit action: 102 | 103 | ``` jsx 104 | class LoginForm extends React.Component { 105 | constructor(props) { 106 | super(props) 107 | 108 | this.state = { 109 | password: '' 110 | } 111 | } 112 | 113 | onSubmit(e) { 114 | if (this.state.password.length < 5) { 115 | e.preventDefault() 116 | alert('oooops') 117 | } 118 | 119 | // Happy path code... 120 | } 121 | 122 | render() { 123 | return ( 124 |
125 | 126 | this.setState({password: e.target.value})} /> 127 | 128 |
129 | ) 130 | } 131 | } 132 | ``` 133 | 134 | As you see, you can define interactions with inline functions: 135 | 136 | ``` jsx 137 | onChange={e => this.setState({password: e.target.value})} 138 | ``` 139 | 140 | as well as component methods: 141 | 142 | ``` jsx 143 | onSubmit={this.onSubmit } 144 | ``` 145 | 146 | The differences between the 2 are subtle -- don't worry about them now. 147 | 148 | ## Components altogether 149 | 150 | To build your UI, you will want to integrate multiple components together. 151 | 152 | Let's build a simple view that presents 2 login forms, one for regular users and 153 | one for admins: 154 | 155 | ``` jsx 156 | class MyView extends React.Component { 157 | render() { 158 | return ( 159 |
160 | 161 | 162 |
163 | ) 164 | } 165 | } 166 | ``` 167 | 168 | Ouch, that was easy! In order to include components in other components you can 169 | simply "embed" them as HTML / XML tags: we have [2 forms](https://jsfiddle.net/0cv3dgko/) now! 170 | 171 | Now, you remember how I told you earlier to forget about those "props"? Let's 172 | get back to them! 173 | 174 | Say that we want to make sure the UI clearly states the forms are for different 175 | users, we can "tag" our components with different attributes: 176 | 177 | ``` jsx 178 | class MyView extends React.Component { 179 | render() { 180 | return ( 181 |
182 | 183 | 184 |
185 | ) 186 | } 187 | } 188 | ``` 189 | 190 | and in our `LoginForm` we can access these "tags" via the `props`, which is a 191 | shortcut for "component's properties", or "properties", or "props": 192 | 193 | ``` jsx 194 | class LoginForm extends React.Component { 195 | constructor(props) { 196 | super(props) 197 | 198 | ... 199 | } 200 | 201 | render() { 202 | return ( 203 |
this.onSubmit(e)}> 204 |
205 | This is the form for the {this.props.role} user 206 |
207 | 208 | ... 209 |
210 | ) 211 | } 212 | } 213 | ``` 214 | 215 | [Et voila!](https://jsfiddle.net/ycbe2vrs/) 216 | 217 | Let's say the **props are something we inherit from our parent component** 218 | (some sort of external initialization parameters), whereas 219 | the **state is something that belongs to the component only**. 220 | 221 | As I said earlier, changing the state triggers a re-render of our component, but 222 | React is smart enough to trigger a re-render when the props change as well: 223 | 224 | ``` jsx 225 | class MyView extends React.Component { 226 | constructor(props) { 227 | super(props) 228 | 229 | this.state = { 230 | adminName: "admin" 231 | } 232 | 233 | setTimeout(_ => { 234 | this.setState({adminName: 'cthulhu'}) 235 | }, 1000) 236 | } 237 | 238 | render() { 239 | return ( 240 |
241 | 242 | 243 |
244 | ) 245 | } 246 | } 247 | ``` 248 | 249 | As simple as [that](https://jsfiddle.net/r5p942h2/)! 250 | 251 | ## Lifecycle methods 252 | 253 | As we saw, React takes advantage of your components implementing some "common" 254 | method, like `render`. There are quite a few more methods you can implement 255 | in your components that will be used by React -- let's call them [lifecycle 256 | methods](https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1) 257 | since they run at different stages of the component's lifecycle. 258 | 259 | The only method I want to mention here is `shouldComponentUpdate(nextProps, nextState)`, 260 | which allows you to decide whether the component should trigger a re-render when 261 | it receives new props (the parent changes) or new state (via `this.setState({...})`): 262 | 263 | ``` jsx 264 | shouldComponentUpdate(nextProps, nextState) { 265 | if (this.state.adminName === nextState.adminName) { 266 | alert('avoided a re-render') 267 | return false 268 | } 269 | 270 | return true 271 | } 272 | ``` 273 | 274 | You can see it in action [here](https://jsfiddle.net/2fyrw3hq/). 275 | 276 | Why did I decide to mention it? Using `shouldComponentUpdate` effectively 277 | translates in good performance optimizations, since you can avoid re-rendering 278 | your components. More on this in the links at the bottom of this guide. 279 | 280 | You are now equipped with enough to start writing your first 281 | React app: let me just add a couple more paragraphs to clarify some things. 282 | 283 | ## Not only web 284 | 285 | I'd like to stress on the fact that, in my opinion, 286 | **React is an approach more than a library**: the idea is that you have 287 | re-usable components that a library (React) renders and manages, while you focus 288 | on how your components live & interact with each other. 289 | 290 | Our examples run on the browser, but the React team has been working on renderers 291 | for [mobile applications](https://facebook.github.io/react-native/docs/getting-started.html) 292 | and [VR browsers](https://facebook.github.io/react-vr/) among others. 293 | 294 | At the end of the day what changes is how to render what's returned by the `render` method, 295 | but everything else (the component's lifecycle & inner workings) stays the same 296 | across platforms. 297 | 298 | ## ...what now? 299 | 300 | We barely scratched the surface, but you should be good to go and build your 301 | first React app. A few pointers for the curious ones: 302 | 303 | * a [primer on virtual DOM](https://www.codecademy.com/articles/react-virtual-dom), which is a great performance optimization React popularized 304 | * what's this weird XML in the `render` function? Meet [JSX](https://jsx.github.io/)! 305 | * [React's top-level API](https://reactjs.org/docs/react-api.html) 306 | * how to embed a component **inside** another component tag? Meet [this.props.children](https://learn.co/lessons/react-this-props-children)! 307 | * re-rendering is sometimes expensive, so you should consider using [pure components](https://60devs.com/pure-component-in-react.html) and [immutable objects](https://github.com/facebook/immutable-js/wiki/Immutable-as-React-state) 308 | * remember when I said the differences between using methods and inline functions 309 | is subtle? [This article](https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578) will give you a good overview 310 | 311 | 312 | ``` 313 | ~/projects/react-in-1000-words$ pandoc README.md | lynx -stdin -dump | wc -w 314 | 1274 315 | ``` 316 | 317 | Ok, I cheated a bit... 318 | --------------------------------------------------------------------------------