React Hooks

一. why hooks:

在React conference 2018上, React团队指出了React社区中被广泛关注的问题:
(1) 逻辑复用问题: react中,组件是构建应用的基本组成部分, 为了组件更好地复用,目前存在两种方案: 高阶组件(HOC)Render props,这些方案都有不同的适用场景,但是也带来了明显的缺点,如组件地狱

(2)巨型组件(Giant components):组件中各种的生命周期函数,但是组件的逻辑是相似的,如componentDidMount和ComponentDidUpdate的时候都可能存在发送ajax请求 或者是相反的, 如componentDidMount和componentWillUnMount会添加/清除绑定的事件, 计时器等
React Hooks_第1张图片
(3)class component还是functional component

  • functional component简单, 但是无法确保以后会不会添加其他的生命周期函数, 造成组件重写,
  • class component要写的代码多,不够简练, 还要面临 this这类烦人的问题; 难以进编译器行优化, 不利于热加载

代码演示
链接
1. [state, useState]

class Greeting extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'Allen'
    }
    this.handleNameChange = this.handleNameChange.bind(this);
  }
  handleNameChange(e) {
    this.setState({
      name: e.target.value
    })
  }
  
  render() {
    return (
      
       
     
    )
  }
}

ReactDOM.render(
  , 
  document.querySelector('#root')
)

将class component换成 functional component是这样的, 是不是简洁了好多!

function Greeting(props) {
  const [name, setName] = React.useState('Marry')
  
  function handleNameChange(e) {
    setName(e.target.value);
  }
  
  return (
      
       
     
    )
}

注意这里的

 const [name, setName] = React.useState('Marry'); // resource为值, setResource为设置值的函数, []里面的命名可以任意

2. useContext

const locale = React.createContext('English');


          {LocaleContext => (
            
              {LocaleContext}
            
          )}
          

使用useContext进行替换

let LocalContext = React.createContext('English')

const locale = React.useContext(LocaleContext);

        {locale}

3.useEffect
假设现在需要体添加一个myName的div来实时显示当前的名称, 我们可以使用componentDidMount和componentDidUpdate的方法

this.state = {
      name: 'Allen',
      myName: '',
    }
    
   componentDidMount() {
    this.state.myName = this.state.name;
  }
  componentDidUpdate() {
    this.state.myName = this.state.name;
  }
  

          
{this.state.myName}

使用useEffect方法

const [myName, setMyName] = React.useState('');
  
  React.useEffect(() => {
    setMyName(name);
  })

看完上面的api你可能会认为, hooks就是为了让functional component具有state和lifecycle method, 实际上并不完全是,hooks的更大用处在于代码的复用

二. hooks是如何进行代码复用的

假设我们有这样一个useEffect的逻辑, 接受一个resource参数, 返回一个resource array, 我们提取出一个useResource函数

import { useState, useEffect } from 'react';
import axios from 'axios';

const useResources = resource => {
  const [resources, setResources] = useState([]);
  useEffect(
    () => {
      (async resource => {
        const response = await axios.get(
          `https://jsonplaceholder.typicode.com/${resource}`
        );
        setResources(response.data);
      })(resource);
    },
    [resource]
  );
  return resources;
};

export default useResources;

引用

import React from 'react';
import useResources from './useResources';

const UserList = () => {
  const users = useResources('users');

  return (
    
    {users.map(user => (
  • {user.name}
  • ))}
); }; export default UserList;

另外一个代码复用的例子:

class App extends React.Component {
  state = { lat: null, errorMessage: '' };

  componentDidMount() {
    window.navigator.geolocation.getCurrentPosition(
      position => this.setState({ lat: position.coords.latitude }),
      err => this.setState({ errorMessage: err.message })
    );
  }

  renderContent() {
    if (this.state.errorMessage && !this.state.lat) {
      return 
Error: {this.state.errorMessage}
; } if (!this.state.errorMessage && this.state.lat) { return ; } return ; } render() { return
{this.renderContent()}
; } }

获取地理位置的函数可以单独抽取出来useLocation.js

import { useState, useEffect } from 'react';

export default () => {
  const [lat, setLat] = useState(null);
  const [errorMessage, setErrorMessage] = useState('');

  useEffect(() => {
    window.navigator.geolocation.getCurrentPosition(
      position => setLat(position.coords.latitude),
      err => setErrorMessage(err.message)
    );
  }, []);

  return [lat, errorMessage]; //注意这里的返回值
};

在App.js中

import useLocation from './useLocation';

const App = () => {
    const  [lat, errorMessage] = useLocation() // 一行代码
    
    const renderContent = () => {
      if (errorMessage && !lat) {
        return 
Error: {errorMessage}
; }; if (!errorMessage && lat) { return ; }; return ; } return
{renderContent()}
; }

你可能感兴趣的:(react)