React 16.8 Hooks 嘗鮮體驗

導讀


  • Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性,編寫具有 Hook 的函數(shù)組件對比以前的 class 組件來說,其好處有以下幾點:
    1 . 不再有生命周期函數(shù)
    2 . 不再有 this 指向
    3 . 函數(shù)式編程
    4 . 不用引入額外的狀態(tài)管理

例子:

  • useState(存儲狀態(tài)和改變狀態(tài)的函數(shù))
import  React, { useState } from "react";

const App = () => {
  const [count, setCount] = useState(0);    // useState中的為count初始值 
  return (
    <div className="App">
      <p>You clicked {count} times!</p>
      <button onClick={() => setCount(count + 1)}>提交</button>
    </div>
  );
};

export default App;
  • useEffect(可以理解為具有以前 class 的 ComponentDidMount,ComponentDidUpdate,ComponentWillUnMount 鉤子功能的副作用函數(shù))
import React, { useState, useEffect } from "react";
import { BrowserRouter, Route, Link } from "react-router-dom";

const Home = () => {
  useEffect(() => {
    console.log(`useEffect => 來了老弟 - Home`);   // 只要組件加載或更新都會執(zhí)行
    return () => {
      console.log(`Home - 走了`);
    };  // 用來清除本次副作用,當組件執(zhí)行下一次副作用函數(shù)時會執(zhí)行
  }, []);    
// useEffect第二個參數(shù)傳空值代表當該組件卸載(ComponentWillUnMount)時才執(zhí)行清除副作用函數(shù)(return的函數(shù))
// useEffect第二個參數(shù)不為空值,則對應當依賴值改變時才執(zhí)行副作用函數(shù),清除副作用函數(shù)執(zhí)行機制同上
  return <h2>Vern.com</h2>;
};

const List = () => {
  useEffect(() => {
    console.log(`useEffect => 來了老弟 - PageList`);
    return () => {
      console.log(`PageList - 走了`);
    };
  }, []);
  return <h2>ListPage</h2>;
};

const Counter = () => {
  let count = useContext(CountContext);
  return <h2>{count}</h2>;
};

const App = () => {
  const [count, setCount] = useState(0);
  useEffect(() => {
    console.log(`useEffect => you clicked ${count} times!`);  // 每次渲染/更新都會執(zhí)行
  });
  return (
    <div className="App">
      <p>You clicked {count} times!</p>
      <button onClick={() => setCount(count + 1)}>提交</button>
      <BrowserRouter>
        <ul>
          <li>
            <Link to="/">首頁</Link>
          </li>
          <li>
            <Link to="/list">列表</Link>
          </li>
        </ul>
        <Route path="/" exact component={Home} />
        <Route path="/list" exact component={List} />
      </BrowserRouter>
    </div>
  );
};

export default App;

當 useEffect 第二個參數(shù)設為空值時:


useEffect1

useEffect2

當不設置 useEffect 第二個參數(shù)時(默認只要組件有變化就會執(zhí)行解綁函數(shù)):


image.png
  • useContext(用于父子組件傳值)
import React, { useState, createContext, useContext } from "react";

const CountContext = createContext();

const Counter = () => {
  let count = useContext(CountContext);
  return <h2>{count}</h2>;
};

const App = () => {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <p>You clicked {count} times!</p>
      <button onClick={() => setCount(count + 1)}>提交</button>
      <CountContext.Provider value={count}>
        <Counter />
      </CountContext.Provider>
    </div>
  );
};

export default App;
  • useReducer(類似 Redux 的 reducer)
import React, { useReducer } from "react";

const init = initialCount => {
  return { count: initialCount };
};

const countReducer = (state, action) => {
  switch (action.type) {
    case "add":
      return { count: state.count + 1 };
    case "sub":
      return { count: state.count - 1 };
    case "reset":
      return init(action.payload);
    default:
      throw new Error();
  }
};

const App = () => {
  const [state, dispatch] = useReducer(countReducer, 0, init);
  // useReducer 第二個參數(shù)為狀態(tài)的初始值,第三個參數(shù)是自定義函數(shù)

  return (
    <>
      <h2>現(xiàn)在的分數(shù)是{state.count}分</h2>
      <button onClick={() => dispatch({ type: "reset", payload: 0 })}>
        Reset
      </button>
      <button onClick={() => dispatch({ type: "add" })}>+</button>
      <button onClick={() => dispatch({ type: "sub" })}>-</button>
    </>
  );
};

export default App;
  • useContext 和 useReducer 做類似 Redux 的功能
    默認紅色

    點擊變藍

    點擊變黃
// 入口文件
import React from "react";
import Body from "./views/home/body";
import Header from "./views/home/header";
import { Color } from './views/home/hooks';   
// 類似 Hoc 導出通過 ColorContext 包裹后的組件,也就是使用傳遞過來的狀態(tài)

const App = () => {
  return (
    <>
      <Color>
        <Header />
        <Body />   
      </Color>
    </>
  );
};

export default App;
import React, { useContext } from "react";
import { ColorContext } from "./hooks";

const Header = () => {
  const {home} = useContext(ColorContext);
  return <p style={{color: home.color}}>我是一段變色文字</p>;
};

export default Header;
import React, { useContext } from "react";
import { ColorContext, CHNAGE_COLOR } from "./hooks";

const Body = () => {
  const { dispatch } = useContext(ColorContext);
  return (
    <>
      <button onClick={() => dispatch({type: CHNAGE_COLOR, color: 'blue'})}>藍色</button>
      <button onClick={() => dispatch({type: CHNAGE_COLOR, color: 'yellow'})}>黃色</button>
    </>
  );
};

export default Body;
import React, { createContext, useReducer } from "react";

export const ColorContext = createContext({});

export const CHNAGE_COLOR = "change_color";

const reducer = (state, action) => {
  switch (action.type) {
    case CHNAGE_COLOR:
      return {
        ...state,
        color: action.color
      };
    default:
      return state;
  }
};

export const Color = props => {
  const [home, dispatch] = useReducer(reducer, { color: "red" });
  return (
    <ColorContext.Provider value={{ home, dispatch }}>
      {props.children}
    </ColorContext.Provider>
  );
};

總結

  • 個人的話目前使用還是不太熟悉,但是能理清邏輯調用,至于實踐上真正優(yōu)秀的地方暫時還沒什么感覺,全局 useReducer 同理使用,對應一個全局 createContext,大家可以去 React 官網查閱相關用法,這里只供個人加深印象而作 ^ _ ^.
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容