No Result
View All Result
CloudReports
  • Home
  • Linux
  • Web development
  • Javascript
  • SQL
  • Ant Design tutorial
  • QR Code Scanner
  • Home
  • Linux
  • Web development
  • Javascript
  • SQL
  • Ant Design tutorial
  • QR Code Scanner
No Result
View All Result
CloudReports
No Result
View All Result
Home Javascript

In-depth explanation about React Hooks – What is React Hooks?

Alicja Zelazko by Alicja Zelazko
June 28, 2019
in Javascript, React
Reading Time: 10 mins read
0
0
SHARES
498
VIEWS
Share on FacebookShare on Twitter

Contents

  • 1 What is React Hooks?
  • 2 READ ALSO
  • 3 Configuring VS Code for Node/JavaScript Development
  • 4 How does Nodejs solve the problem of high concurrency?
    • 4.1 Hooks API
    • 4.2 useState
    • 4.3 useReducer
    • 4.4 useEffect
    • 4.5 useMemo
    • 4.6 useContext
    • 4.7 useRef
  • 5 React state sharing scheme
    • 5.1 Mixins
    • 5.2 HOC
    • 5.3 Render Props
    • 5.4 Hooks
  • 6 React Hooks design concept
  • 7 Fundamental
  • 8 Functional implementation
    • 8.1 Capture props
    • 8.2 Function component
    • 8.3 useEffect is called every time it is rendered, and it can be used as a lifecycle with a little wrapper;
    • 8.4 Principle of implementation
  • 9 Come to a set of combination punches!
    • 9.1 Since each Hooks API is a pure function concept, it pays more attention to input and output. Therefore, it is better to assemble the function and combine the basic Hooks APIs of different features to create a new one. Hooks of features.
  • 10 useState maintains component state
  • 11 useWillUnmount
  • 12 As mentioned in the useEffect, it allows to return a cleanup function, the component will execute the cleanup function when unmounting, so useWillUnmount can also be easily implemented~
    • 12.1 useHover
    • 12.2 useField
    • 12.3 Precautions
  • 13 Precautions
  • 14 Conclusion
    • 14.1 References:
Rate this post

What is React Hooks?

Hooks, as the name implies, is literally the concept of a React hook. Through a case, we have the first impression of React Hooks.

READ ALSO

Configuring VS Code for Node/JavaScript Development

Configuring VS Code for Node/JavaScript Development

August 2, 2021
809
How does Nodejs solve the problem of high concurrency?

How does Nodejs solve the problem of high concurrency?

July 18, 2021
888

Suppose now that you want to implement a component of a counter. If we use componentization, we need to do a lot more things, such as declaring state, writing counters, etc., and there are more concepts to understand, such as the concept of Javascript classes, the context of this context, etc. .

Example

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

class Counter extends React.Component {
  state = {
  	count: 0
  }

  countUp = () => {
    const { count } = this.state;
  	this.setState({ count: count + 1 });
  }
  
  countDown = () => {
    const { count } = this.state;
  	this.setState({ count: count - 1 });
  }
  
  render() {
    const { count } = this.state;
  	return (
      <div>
        <button onClick={this.countUp}>+</button>
        <h1>{count}</h1>
        <button onClick={this.countDown}>-</button>
      </div>
    )
  }
}

ReactDOM.render(<Counter />, document.getElementById('root'));

With React Hooks, we can write this.

Example

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>+</button>
      <h1>{count}</h1>
      <button onClick={() => setCount(count - 1)}>-</button>
    </div>
  )
}

ReactDOM.render(<Counter />, document.getElementById('root'));

Through the above example, it is obvious that React Hooks provides a compact, functional (FP) program style that implements state-to-UI interaction (MVVM) through pure function components and controllable data streams.

Hooks API

  • Basic Hooks
    • useState
    • useEffect
    • useContext
  • Additional Hooks
    • useReducer
    • useCallback
    • useMemo
    • useRef
    • useImperativeHandle
    • useLayoutEffect
    • useDebugValue

useState

useState is the most basic API, it passes in an initial value, and each function can get a new value.

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>+</button>
      <h1>{count}</h1>
      <button onClick={() => setCount(count - 1)}>-</button>
    </div>
  )
}

ReactDOM.render(<Counter />, document.getElementById('root'));

It should be noted that the state count obtained by useState is represented as a constant in the Counter component. Each time it is modified by setCount, it re-acquires a new constant through useState.

ADVERTISEMENT

useReducer

useReducer and useState are almost identical, requiring an external reducer (global), in this way multiple states can be controlled simultaneously. Looking closely, it is very close to the concept of data flow in redux.

import { useState, useReducer } from 'react';
import ReactDOM from 'react-dom';

function reducer(state, action) {
  switch (action.type) {
    case 'up':
      return { count: state.count + 1 };
    case 'down':
      return { count: state.count - 1 };
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 1 })
  return (
    <div>
      {state.count}
      <button onClick={() => dispatch({ type: 'up' })}>+</button>
      <button onClick={() => dispatch({ type: 'down' })}>+</button>
    </div>
  );
}

ReactDOM.render(<Counter />, document.getElementById('root'));

useEffect

A vital Hooks API, as its name implies, useEffect is used to handle the side effects of various state changes, that is, the logic that will only be executed at a particular moment.

import { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

function Example() {
  const [count, setCount] = useState(0);

  
  useEffect(() => {
    
    document.title = `You clicked ${count} times`;
    
    return function cleanup() {
    	document.title = 'app';
    }
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));

useMemo

useMemo is mainly used for rendering process optimization. The two parameters are the calculation function (usually the component function) and the dependency state list. When the state of the dependency changes, the execution of the calculation function is triggered. If no dependencies are specified, the calculation function is executed every rendering process.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
import { useState, useMemo } from 'react';
import ReactDOM from 'react-dom';

function Time() {
	return <p>{Date.now()}</p>;
}

function Counter() {
  const [count, setCount] = useState(0);
  
  const memoizedChildComponent = useMemo((count) => {
    return <Time />;
  }, [count]);

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>+</button>
      <div>{memoizedChildComponent}</div>
    </div>
  );
}

ReactDOM.render(<Counter />, document.getElementById('root'));

useContext

Context is the state of external create, internal use, and the difference between it and global variables is that if multiple components use context at the same time, then these components will be re-render. If multiple components useState with the same global variable, only the current component that triggers setState will be triggered. Rerender.

Example – unused useContext

import { useState, useContext, createContext } from 'react';
import ReactDOM from 'react-dom';


const UserContext = new createContext();


const UserProvider = props => {
  let [username, handleChangeUsername] = useState('');
  return (
    <UserContext.Provider value={{ username, handleChangeUsername }}>
      {props.children}
    </UserContext.Provider>
  );
};

// 3. Create Consumer
const UserConsumer = UserContext.Consumer;

// 4. Use Consumer Package component
const Pannel = () => (
  <UserConsumer>
    {({ username, handleChangeUsername }) => (
      <div>
        <div>user: {username}</div>
        <input onChange={e => handleChangeUsername(e.target.value)} />
      </div>
    )}
  </UserConsumer>
);

const Form = () => <Pannel />;

const App = () => (
  <div>
    <UserProvider>
      <Form />
    </UserProvider>
  </div>
);

ReactDOM.render(<App />, document.getElementById('root'));

Example – Using the useContext

import { useState, useContext, createContext } from 'react';
import ReactDOM from 'react-dom';

const UserContext = new createContext();

const UserProvider = props => {
  let [username, handleChangeUsername] = useState('');
  return (
    <UserContext.Provider value={{ username, handleChangeUsername }}>
      {props.children}
    </UserContext.Provider>
  );
};

const Pannel = () => {
  const { username, handleChangeUsername } = useContext(UserContext); // 3. 使用 Context
  return (
    <div>
      <div>user: {username}</div>
      <input onChange={e => handleChangeUsername(e.target.value)} />
    </div>
  );
};

const Form = () => <Pannel />;

const App = () => (
  <div>
    <UserProvider>
      <Form />
    </UserProvider>
  </div>
);

ReactDOM.render(<App />, document.getElementById('root'));

useRef

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will last the entire component’s life cycle. In fact, useRef is a very useful API. In many cases, we need to save some changes, it will come in handy.

Example

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

React state sharing scheme

When it comes to state sharing, the easiest and most straightforward way is to pass state through props. This method is coupled with the parent-child relationship of the component. Once the component nesting structure changes, the code needs to be rewritten, and the maintenance cost is very expensive. Over time, various programs have been officially introduced to address the issue of state sharing and code reuse.

Mixins

In React, only components created with createClass can use mixins. This high coupling relies on uncontrollable, high-complexity approaches that have faded out of the historical arena with the wave of ES6.

HOC

Higher-order components are derived from functional programming. Since components in React can also be treated as functions (classes), code reuse can be achieved by HOC. It can be implemented by attribute proxy and reverse inheritance. HOC can easily manipulate the result of rendering, and can also operate on the props/state of the component, so that complex code logic multiplexing can be conveniently performed.

import React from 'react';
import PropTypes from 'prop-types';

class Show extends React.Component {
  static propTypes = {
    children: PropTypes.element,
    visible: PropTypes.bool,
  };

  render() {
    const { visible, children } = this.props;
    return visible ? children : null;
  }
}


function Show2(WrappedComponent) {
  return class extends WrappedComponent {
    render() {
      if (this.props.visible === false) {
        return null;
      } else {
        return super.render();
      }
    }
  }
}

function App() {
	return (
  	<Show visible={Math.random() > 0.5}>hello</Show>
  );
}

State multiplexing in Redux is a typical implementation of HOC. We can assemble data into target components through compose, but you can also handle it through decorators.

import React from 'react';
import { connect } from 'react-redux';


@connect(state => ({ name: state.user.name }))
class App extends React.Component{
  render() {
     return <div>hello, {this.props.name}</div>
  }
}


connect((state) => ({ name: state.user.name }))(App);

Render Props

Obviously, renderProps is a way to pass the render method as a prop to a child component. Compared to the HOC solution, renderProps can protect the original component hierarchy.

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';

class Mouse extends React.Component {
  static propTypes = {
    render: PropTypes.func.isRequired
  }

  state = { x: 0, y: 0 };

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
        {this.props.render(this.state)}
      </div>
    );
  }
}

function App() {
  return (
    <div style={{ height: '100%' }}>
      <Mouse render={({ x, y }) => (
          // render prop 给了我们所需要的 state 来渲染我们想要的
          <h1>The mouse position is ({x}, {y})</h1>
        )}/>
    </div>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));

Hooks

By combining the Hooks API with React&#39;s built-in Context, you can see from the previous example that Hook makes state sharing between components clearer and simpler.

React Hooks design concept

Fundamental

function FunctionalComponent () {
  const [state1, setState1] = useState(1);
  const [state2, setState2] = useState(2);
  const [state3, setState3] = useState(3);
}

 

{
  memoizedState: 'foo',
  next: {
    memoizedState: 'bar',
    next: {
      memoizedState: 'bar',
      next: null
    }
  }
}

Functional implementation

Capture props

Function components are inherently supported for props, and the basic usage is not much different from the class components. The two differences that need to be noted are:

  • The class component props are mounted in this context, and the functional component is passed in by the formal parameter;
  • Due to the difference in mount position, if this changes in the class component, this.props will also change; in the function component props is always immutable, so follow the capture value principle (that is, the value obtained is always At some point in time, Hooks also follows this principle.

To understand the capture value with an example, we can use the useRef to evade the capture value because the useRef is mutable.stateClass component

Function component

Creation status this.state = {}
useState, useReducer Modify status this.setState()
set function Update mechanism Asynchronous update, multiple modifications merged to the previous state, resulting in a copy
Synchronous update, directly modified to target status State management One state centrally manages multiple states
Multiple states, state merge can be done via useReducer (manual) performance high
If the useState initialization state needs to be obtained through very complicated calculations, please use the declaration method of the function, otherwise, it will be executed repeatedly for each rendering. The life cycle componentDidMount / componentDidUpdate / componentWillUnMount

useEffect is called every time it is rendered, and it can be used as a lifecycle with a little wrapper;

  • shouldComponentUpdate

Usually, when we optimize component performance, we prefer to use pure components to reduce the number of renderings of individual components.

  • Reuse Hooks can be replaced by useMemo, which can re-render components only when some data changes, equivalent to shouldComponentUpdate with shallowEqual.

Force rendering forceUpdate

class Button extends React.PureComponent {}

Since by default, each modification state will cause re-rendering, it can be used as a forceUpdate through a set function that is not used.

Principle of implementation

Enhance Hooks based on Hooks

const forceUpdate = () => useState(0)[1];

Come to a set of combination punches!

Since each Hooks API is a pure function concept, it pays more attention to input and output. Therefore, it is better to assemble the function and combine the basic Hooks APIs of different features to create a new one. Hooks of features.

useState maintains component state

useEffect handles side effects

  • useContext listens for provider update changes
  • useDidMount
  • useDidUpdate

useWillUnmount

import { useEffect } from 'react';

const useDidMount = fn => useEffect(() => fn && fn(), []);

export default useDidMount;

As mentioned in the useEffect, it allows to return a cleanup function, the component will execute the cleanup function when unmounting, so useWillUnmount can also be easily implemented~

import { useEffect, useRef } from 'react';

const useDidUpdate = (fn, conditions) => {
  const didMoutRef = useRef(false);
  useEffect(() => {
    if (!didMoutRef.current) {
      didMoutRef.current = true;
      return;
    }
    
    return fn && fn();
  }, conditions);
};

export default useDidUpdate

useHover

Example

import { useEffect } from 'react';

const useWillUnmount = fn => useEffect(() => () => fn && fn(), []);

export default useWillUnmount;

useField

Example

import { useState } from 'react';
const useHover = () => {
  const [hovered, set] = useState(false);
  return {
    hovered,
    bind: {
      onMouseEnter: () => set(true),
      onMouseLeave: () => set(false),
    },
  };
};

export default useHover;
import { useHover } from './lib/onHover.js';

function Hover() {
  const { hovered, bind } = useHover();
  return (
    <div>
      <div {...bind}>
        hovered:
        {String(hovered)}
      </div>
    </div>
  );
}

Precautions

The scope of use of Hook: in the functional React component, in the custom Hook function;

import { useState } from 'react';

const useField = (initial) => {
  const [value, set] = useState(initial);

  return {
    value,
    set,
    reset: () => set(initial),
    bind: {
      value,
      onChange: e => set(e.target.value),
    },
  };
}

export default useField;
import { useField } from 'lib/useField';

function Input {
  const { value, bind } = useField('Type Here...');

  return (
    <div>
      input text:
      {value}
      <input type="text" {...bind} />
    </div>
  );
}

function Select() {
  const { value, bind } = useField('apple')
  return (
    <div>
      selected:
      {value}
      <select {...bind}>
        <option value="apple">apple</option>
        <option value="orange">orange</option>
      </select>
    </div>
  );
}

Precautions

  • The scope of use of Hook: in the functional React component, in the custom Hook function;
  • Hook must be written at the outermost layer of the function. Each time useState changes its cursor, and React updates the state according to its order.
  • Although the Hook API is executed every time the render is executed, the resulting state is always a constant (the scope is inside the function);

Conclusion

React Hooks provides new possibilities for state management, although we may need to maintain some internal state, but avoid dealing with state management issues in complex ways such as renderProps / HOC. The benefits of Hooks are as follows:

  • More granular code reuse without excessive side effects
  • Functional programming style, code is more concise while reducing the threshold for use and understanding
  • Reduce component nesting levels
  • Component data flow is clearer

In fact, by customizing custom Hooks in various scenarios, our application is more convenient and concise, the hierarchy of components is guaranteed to be intact, and there is such a pleasing functional programming style, Hooks in React 16.8 The .0 version has been officially released for a stable version, so let’s get started! ! !

References:

https://reactjs.org/docs/hooks-reference.html

https://github.com/beizhedenglong/react-hooks-lib

https://overreacted.io/how-are-function-components-different-from-classes/

Tags: Additional HooksBasic Hookshooks-referencereact-hooks-libReact.js
ShareTweetShare
Previous Post

Next.js + Ant Design with less – Advanced Nextjs and Ant design scaffolding

Next Post

15 best JavaScript code compression tools – Updated 2019

Alicja Zelazko

Alicja Zelazko

Related Posts

Configuring VS Code for Node/JavaScript Development
Javascript

Configuring VS Code for Node/JavaScript Development

August 2, 2021
809
How does Nodejs solve the problem of high concurrency?
Javascript

How does Nodejs solve the problem of high concurrency?

July 18, 2021
888
Migrate from Hot Reload to Fast Refresh
React

Migrate from Hot Reload to Fast Refresh

December 16, 2020
940
[React] React installation for Mac
React

[React] React installation for Mac

December 16, 2020
81
Npm module: a backdoor and ambush questions
Javascript

Npm module: a backdoor and ambush questions

December 16, 2020
191
NPM: three packets contained malicious code
Javascript

NPM: three packets contained malicious code

December 16, 2020
73
Next Post

15 best JavaScript code compression tools - Updated 2019

Discussion about this post

No Result
View All Result

Categories

  • Android (1)
  • Ant Design tutorial (7)
  • App/Game (2)
  • Javascript (16)
  • Layout and Routing (2)
  • Linux (9)
  • PC & LAPTOP (6)
  • PERSONAL FINANCES (1)
  • React (13)
  • SQL (2)
  • TECHNOLOGY & DIGITAL (7)
  • The Basics (5)
  • Web development (37)

Search

No Result
View All Result

Categories

  • Android (1)
  • Ant Design tutorial (7)
  • App/Game (2)
  • Javascript (16)
  • Layout and Routing (2)
  • Linux (9)
  • PC & LAPTOP (6)
  • PERSONAL FINANCES (1)
  • React (13)
  • SQL (2)
  • TECHNOLOGY & DIGITAL (7)
  • The Basics (5)
  • Web development (37)
No Result
View All Result
  • Home
  • Linux
  • Web development
  • Javascript
  • SQL
  • Ant Design tutorial
  • QR Code Scanner