Starting with mineBlog

I need you to know React, and I want to have a brief understanding of how Hook works and what to pay attention to. React Hook is not described in detail. If you want to learn more about React Hook, check out the official documentation. Because the project is relatively simple, I will write most of the code in detail. It is recommended that you read the table of contents before reading the article to find the chapter you are interested in.

React Hook + Parcel

A few days ago, my girlfriend told me that they needed a Truth or Dare interface for their orientation and wanted me to write one for her. I said, “Oh, I haven’t played React Hook yet, so let’s have a try.” So I spent one night, actually two hours, one hour building the project and one hour writing.

Demo: Souche-truth-or-dare.surge. Sh

Environment set up

First we create a folder and initialize it.

mkdir truth-or-dare
cd truth-or-dare
npm init -y
Copy the code

To install dependencies, react@next react-dom@next parcel- Bundler emotion@9 react-emotion@9 service.

React Hook is still in beta at the time of writing (December 26, 2018) and requires the next version.

Emotion is a relatively complete CSS-IN-JS solution, which is very convenient and appropriate for our project. Also, because the latest version of emotion@10 has some compatibility issues with parcel, see Issue. So the old version of emotion@9 is used here for the time being.

npm i react@next react-dom@next emotion@9 react-emotion@9
npm i parcel-bundler babel-plugin-emotion@9 -D
Copy the code

Create the.babelrc file or write the Babel configuration in package.json:

{
  "plugin": [["emotion", {"sourceMap": true}}]]Copy the code

Create the SRC folder and create index.html


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>The moment of truth</title>
</head>
<body>
  <div id="app"></div>
  <script src="./index.jsx"></script>
</body>
</html>
Copy the code

And the index JSX file

import * as React from 'react'
import { render } from 'react-dom'

render(<div>First Render</div>.document.getElementById('app'))
Copy the code

Finally, add the following scripts to package.json

{
  "start": "parcel serve src/index.html"."build": "rm -rf ./dist && parcel build src/index.html"
}
Copy the code

Finally, we can start the development server successfully by NPM start. Open localhost:1234 in your browser.

The parcel is Hot Reload built in, so no additional configuration is required, right out of the box. Do you feel very simple, with it, manual construction projects are no longer difficult. Of course, TS is also available out of the box, but this time MY project is really small, so I won’t use TS.

UseState is the first Hook to contact

We create an app.jsx to start our actual coding. So let’s take a quick look at this

export default function App() {
  const [selected, setSelected] = useState(The '*')
  const [started, setStarted] = useState(false)

  return (
    <div>
      <div>{selected}</div>
      <button>{started ? 'End' : 'start '}</button>
    </div>)}Copy the code

We’ve done the simplest use of the Hook, of course, without any interaction yet, and you probably don’t understand why this code is useful.

A quick note on useState: This function takes a single argument, an initial value, that can be of any type. It returns a tuple of [any, (v: any) => void]. The first value for State, and the other is a Setter that sets the value for State.

So how do we use this Setter? Just call it where you need it.

<button onClick={() => setStarted(! started)}>{started ? </button>Copy the code

Save, go to the page and click on this button and see if it switches between end and start? SetState ({started:!); setState({started:!); setState({started:! This. State. Started}). However, unlike setState, all data comparisons in Hook are === (strictly equal).

There are many other uses of useState, such as setters that accept a function to pass in the previous value and return the updated value.

UseEffect listens for start and end events

Next, we want to scroll on the screen until I click on the end.

If the requirement were implemented using a Class Component, it would look like this:

  1. Listen for button click events
  2. Decide whether it is the beginning or the end
    • If it’s a start, create a timer that periodically gets a random truth or adventure from the data and updates itselected
    • If it is, delete the timer that was set earlier

It’s very direct, very simple.

With hooks, you can of course do the same, but you also need to introduce an additional State to store the timer, since the function component cannot hold variables. But if we look at it another way:

  1. Listening to thestartedchange
    • If it is a start, create a timer and do the update
    • If yes, delete the timer

Suddenly this is easier. Let’s imagine how to implement this in Class Component.

export default class App extends React.Component {
  componentDidUpdate(_, preState) {
    if (this.state.started ! == preState.started) {if (this.state.started) {
        this.timer = setInterval(/* blahblah*/)}else {
        clearInterval(this.timer)
      }
    }
  }

  render() {
    // blahblah}}Copy the code

Good trouble, and logic around, and if there is a lot of code between componentDidUpdate and render, it will be more difficult to analyze and read the code, if you maintain such code behind, you will cry. But useEffect Hook is different. The painting style is as follows:

export default function App() {
  // The previous code
    
  // When started changes, the passed callback is called
  useEffect((a)= > {
    if (started) {
      const timer = setInterval((a)= > {
        setSelected(chooseOne())
      }, 60)

      return (a)= > clearInterval(timer)
    }
  }, [started])

  return (
    // Return the View)}Copy the code

When React Hook is used, all the logic comes together and the code is clear and easy to read.

UseEffect is literally a part of the code that may have an effect. In some places, it is also called a side effect. But the side effect is that there is a sense that this code is being actively executed rather than passively executed, which is not easy to understand. I think a better explanation is code that executes under the influence of State changes.

Why is that? As you can see, useEffect has a second argument, which is an array. React checks this array to see if each item in the render call has changed from the last render call. If one of the items changes, the callback is called.

When you understand the process, maybe you’ll understand why I’m saying this.

Of course, the second argument can be omitted, which defaults to listening for all State. (You can see that now, but when you dig a little deeper, you’ll see that there are not only State, but also Context and other hooks that can trigger State changes, which I won’t delve into in this article.)

Now, let’s review the timer process again, starting with the code:

if (started) {
  const timer = setInterval((a)= > {
    setSelected(chooseOne())
  }, 60)

  return (a)= > clearInterval(timer)
}
Copy the code

The ideal process would look like this:

  • If so, register the timer. – Done!
  • If it ends, cancel the timer. – Where?

Hey, where did the else branch go? Why did the timer cancel function return in the first branch?

This brings us to the second useEffect feature, which supports not only forward processing but also reverse cleaning. You can return a function as a cleanup function. When effect is called, it calls the cleanup function that effect returned last time (known as destructor) before calling effect this time.

This makes it easy to use this feature to achieve functionality that requires two branches when there is only one branch.

Other Hook

In the Hook, the above two is used very frequently, of course there are other such as useContext useReducer/useCallback useMemo/useRef/useImperativeMethods/useLayoutEffect.

You can create your own hooks, and React follows a convention that all hooks start with use. You can better lint code for ESLint.

These belong to advanced use, interested can go to study, this article is just a primer, not too much explanation.

Let’s add style to Emotion

All right, csS-in-JS is Duang, Duang, Duang. I’ll skip the code.

finishing

JSX

to
.

The final SRC/app.jsx file looks like this:

import React, { useState, useEffect } from 'react'
import styled from 'react-emotion'

const lists = [
  'Name 5 weaknesses of yourself'.'Take a two-week tour'.'Take a selfie for the interns'.'Three hits you say I guess'.'Remember the names of 10 people present.'.'Say your name out loud' I am XXX 'three times'.'Take two selfies for the interns'.'Choose another partner to continue the game'.'Straight through'.'Introduce two little friends.',]function chooseOne(selected) {
  let n = ' '
  do {
    n = lists[Math.floor(Math.random() * lists.length)]
  } while( n === selected)
  return n
}

const Root = styled.div` background: #FF4C19; height: 100vh; width: 100vw; text-align: center; `

const Title = styled.div` height: 50%; font-size: 18vh; text-align: center; color: white; padding: 0 10vw; Font-family :"Microsoft YaHei",Arial,Helvetica,sans-serif,"宋体"; `

const Button = styled.button` outline: none; border: 2px solid white; border-radius: 100px; min-width: 120px; width: 30%; text-align: center; font-size: 12vh; line-height: 20vh; margin-top: 15vh; color: #FF4C19; cursor: pointer; `

export default function App() {
  const [selected, setSelected] = useState(The '-')
  const [started, setStarted] = useState(false)

  function onClick() { setStarted(! started) } useEffect((a)= > {
    if (started) {
      const timer = setInterval((a)= > {
        setSelected(chooseOne(selected))
      }, 60)

      return (a)= > clearInterval(timer)
    }
  }, [started])

  return (
    <Root>
      <Title>{selected}</Title>
      <Button onClick={onClick}>{started ? 'End' : 'start '}</Button>
    </Root>)}Copy the code

Summary replay – Performance issues?

Recently just become a full defense, suddenly found that the word is very good to use, ha ha ha.

Although the use of such a short time, there are still some of their own thinking, said for everyone’s reference.

If you think about it, when you use useEffect, you actually create a new function every time, but not every time you call it. If you use a lot of useEffect in your code, and the code is long, each rendering will cause significant performance problems.

So there are two ways to solve this problem:

  1. Do not do too much logic in Hook, for example, Hook can write some simple display components, such as Tag, Button, Loading, etc., the logic is not complex, the amount of code is small, through Hook writing together can reduce the complexity of the whole component.

  2. Effect is split out and passed in as a parameter. Something like that

    function someEffect(var1, var2) {
        // doSomething
    }
    
    export function App() {
    	// useState...
        useEffect((a)= > someEffect(var1, var2), [someVar])
        // return ....
    }
    Copy the code

    This creates a function, but it’s much faster than creating a function with tens or hundreds of lines of logic. Second, it is not recommended to use the.bind method, which is not as efficient as the function literal.

    This method is not recommended to do manually, you can leave this part of the optimization to the Babel plug-in.

In fact, as a developer, I should not pay too much attention to this part, but performance is the XX point of the programmer, I still subconsciously think in terms of performance. This is just a small optimization direction. I hope the React official can further optimize this part in the future.

You can check the official FAQ for existing optimization solutions

conclusion

After this brief use, I feel that with Hook you can focus more on the writing of logic, rather than the flow of data flow. For some light components is simply more suitable, I hope to be able to officially release the official use of it.

In addition, Parcel offers great built-in functionality that allows us to be as flexible as WebPack but develop faster than webPack.

Ok, one hour to write code, one day to write article hydrology finished. If there is a chance to try further.