react-hook简单使用

一、函数式组件创建

function HelloComponent(props, /* context */) {
  return <div>Hello {props.name}</div>
}
ReactDOM.render(<HelloComponent name="Sebastian" />,document.getElementById("mountNode")) 

这里我们可以知道该组件中并没有自己的状态,但实际开发中往往需要内部的状态实现一系列的交互和展示功能.所以我们用class创建组件更多一点.但是,纯函数的组件式创建更符合react的思想,于是为了解决状态问题,完善的函数式组件创建模式出现:react-hook

首先需要明确的一点是,hook中没有this指针,所以相关的api都需要改变才.

二、常用HOOK API

结合class式组件进行对比

1.组件申明

class:

export default class Text extends React.Component {}

Hook

const Text = {}
export default Text

2.state

(1)初始化

class

constructor(props) {
    super(props);
    this.state = {
      name: '小明',
age:1 }; }

Hook

const [name, setName] = useState(0);
const [age, setAge] = useState(1);
//name:变量名 初始值是useState()里面额值,相当于name=0,同时又申明了一个函数setName并使其具有监听name变化然后更新视图的功能
//setName:传一个新的name值,并更新至视图层.可以是一个具有返回值的函数

(2)获取state值

class

this.state.name
this.state.age

Hook  

const [name, setName] = useState('小明');
const [age, setAge] = useState(1);
useState('小明')//获取name,自动忽略参数
useState(1)//获取age,自动忽略参数

(3)修改state值

class

this.setState({age:18})
//实际上是修改的this.state的里面的元素

Hook

setAge(18)
//传入一个新的age值,自动渲染至视图层.不同于setState(),只能一次设置一个特定变量.

3.props

用法差不多,只不过hook不用初始化,直接将参数拿来用.

4.生命周期

class

componentWillMount //在渲染前调用,在客户端也在服务端。

componentDidMount : //在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。

componentWillReceiveProps //在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。

shouldComponentUpdate //返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。

componentWillUpdate//在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。

componentDidUpdate //在组件完成更新后立即调用。在初始化时不会被调用。

componentWillUnmount//在组件从 DOM 中移除之前立刻被调用。

Hook

生命周期的实质就是回调函数,只不过用不同的生命周期表示不同阶段的回调函数.目前Hook只有一个回调函数useEffect(),但是在多个阶段触发

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

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

  useEffect(() => {
    // 如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMountcomponentDidUpdatecomponentWillUnmount 这三个函数的组合。
    document.title = `You clicked ${count} times`;
  });
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

 另外,useEffect()还可以手动设置依赖项,它可以接收两个参数,第一个是函数,第二个是依赖项(数组),第二个参数给的话就依据依赖项时候更改决定是否调用,不给就类似上面的用法.

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

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

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  },[count]);
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );

5.comtext

具体的需求就是组件之间的的状态共享,比如兄弟之间、爷孙之间,跨组件的状态共享.解决了参数需要逐层往下传递的麻烦.

class

 

// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
    // 无论多深,任何组件都能读取这个值。
    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // 指定 contextType 读取当前的 theme context。
  // React 会往上找到最近的 theme Provider,然后使用它的值。
  // 在这个例子中,当前的 theme 值为 “dark”。
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
} 

Hook

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext); //由于没有了this,所以我们需要用这个api来获取context,然后使用.其他的用法一样

  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}  

6.ref

这里主要针对,ref绑定字符串这种形式的使用.回调函数的用法是一样的,其根本原因还是Hook并没有"this.refs"这种获取ref的方式

class

<input ref="input" />

let inputEl = this.refs.input;//这里拿到对应的ref,然后处理相关逻辑

Hook

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

7.reducer

class

this.props.dispatch({type:'/api'})

Hook

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

 待补充