Workspace
  • Study Book
  • WEB Network HTTP etc
    • Performance Optimization
    • Performance Optimization
    • HTTP/2 & SPDY
    • WebSocket
    • HTTP Header
    • Cross-Origin Resource Sharing
    • JSON, XML, other format
  • Javascript
    • Promise
    • make API call
    • Web API
    • Common JS
    • AJAX
    • Event DOM and delegation
    • ES6 new features
    • special function
    • function API
  • React
    • class component
    • Example
    • Lifting functions/ state up
    • Hot Loader
    • Testing
    • New Features
    • Hook
    • Simple code
    • Life Cycle
  • CSS
    • Horizontal & Vertical Align
    • GPU Animation
    • transform-function
    • LVHA Pseudo-classes
    • Selector
    • How To CSS
  • HTML
  • Redux
  • NodeJS
    • File System
  • express
    • express questions
    • express mongodb
  • Restful API
  • MongoDB
  • Compare
  • Test
    • Jest
  • Deploy development
  • coding question
  • DevOps
  • Webpack
  • GraphQL
Powered by GitBook
On this page
  • useState
  • useEffect & useRef & useContext
  • UseContext
  • Counter Example
  • React Counter using Hooks
  • Using the Effect Hook
  • Custom Hook
  • Class component to functional
  • Hook Use

Was this helpful?

  1. React

Hook

useState

useState() returns an array with exactly two elements:

(1) Your current state value, (2) A method to update your state value.

useState() will replace the old state instead of merging.

import React, { useState } from "react";
import Person from "./Person/Person";

const App = props => {
    const [personState, setPersonState] = useState({
        person: [
            { name: "Harry", age: 24 }
        ]
    });
    
    const [otherState, setOtherState] = useState("some other value");
    
    const switchNameHandler = () => {
        setPersonState({
            person: [
                {name: "Harry Lu", age: 25}
            ]
        });·
    };
    
    return (
        <div className="App">
            <button onClick={switchNameHandler}>Switch Name</button>
            <Person
                name={personState.person[0].name}
                age={personState.person[0].age}
            /> 
        </div>
    );
}

export default App;

useEffect & useRef & useContext

useEffect: componentDidMount · componentDidUpdate componentWillUnmount

import React, { useEffect, useRef, useContext } from 'react';
import AuthContext from '../../context/auth-context';

const cockpit = props => {
  const toggleBtnRef = useRef(null);
  const authContext = useContext(AuthContext);

  useEffect(() => {
    // Http request...
    // same as componentDidMount and componentDidUpdate
    // setTimeout(() => {
    //   alert('Saved data to cloud!');
    // }, 1000);
    toggleBtnRef.current.click();
    return () => {
      // clean-up code here
      // same as componentWillUnmount 
    };
  }, []); // only re-run the effect if the value inside changes

  return (
    <div>
      <button ref={toggleBtnRef}>
        Toggle Persons
      </button>
      <button onClick={authContext.login}>Log in</button>
    </div>
  );
};

export default React.memo(cockpit);

UseContext

recieved a React.createContext

return ---- <MyContext.Provider> value prop

const value = useContext(MyContext);

Counter Example

import React, { useState } from "react";

const App = (props) => {

  const [counter, setCounter] = useState(0);

  return (
    <React.Fragment>
      <span>You Clicked {counter} times!</span>
      <button onClick={() => setCounter(counter + 1)}>Increase</button>
      <button onClick={() => setCounter(counter - 1)}>Decrease</button>
    </React.Fragment>
  );
}

export default App;

React Counter using Hooks

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

function App() {
  const [num, setNum] = useState(Number(localStorage.getItem("num")) || 0);

  useEffect(() => {
    localStorage.setItem("num", num);
  }, [num]);

  return (
    <div>
      {num}
      <button onClick={() => setNum(num + 1)}>Add</button>
      <button onClick={() => setNum(num - 1)}>Subtract</button>
    </div>
  );
}

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

Using the Effect Hook

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

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';

useEffect lets us express different kinds of side effects after a component renders. Some effects might require cleanup so they return a function

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

Use Multiple Effects to Separate Concerns

you can use the State Hook more than once, you can also use several effects. This lets us separate unrelated logic into different effects:

Custom Hook

A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks.

import { useState, useEffect } from 'react';

function useFriendStatus(friendID) {  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}


function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

Class component to functional

Hook Use

Only in top of react function. Not in conditional control language

react use linked list hooks to rank

const [name,setName] = useState('leo');
///
setName('Lily');
// Some code
// 进入 mounState 逻辑

function mountState(initialState) {

  // 将新的 hook 对象追加进链表尾部
  var hook = mountWorkInProgressHook();

  // initialState 可以是一个回调,若是回调,则取回调执行后的值

  if (typeof initialState === 'function') {

    // $FlowFixMe: Flow doesn't like mixed types

    initialState = initialState();
  }

  // 创建当前 hook 对象的更新队列,这一步主要是为了能够依序保留 dispatch

  const queue = hook.queue = {

    last: null,

    dispatch: null,

    lastRenderedReducer: basicStateReducer,

    lastRenderedState: (initialState: any),

  };

  // 将 initialState 作为一个“记忆值”存下来

  hook.memoizedState = hook.baseState = initialState;

  // dispatch 是由上下文中一个叫 dispatchAction 的方法创建的,这里不必纠结这个方法具体做了什么

  var dispatch = queue.dispatch = dispatchAction.bind(null, currentlyRenderingFiber$1, queue);

  // 返回目标数组,dispatch 其实就是示例中常常见到的 setXXX 这个函数,想不到吧?哈哈

  return [hook.memoizedState, dispatch];
}



mountWorkInProgressHook :


function mountWorkInProgressHook() {

  // 注意,单个 hook 是以对象的形式存在的
  var hook = {

    memoizedState: null,

    baseState: null,

    baseQueue: null,

    queue: null,

    next: null

  };

  if (workInProgressHook === null) {
    // 这行代码每个 React 版本不太一样,但做的都是同一件事:将 hook 作为链表的头节点处理
    firstWorkInProgressHook = workInProgressHook = hook;
  } else {
    // 若链表不为空,则将 hook 追加到链表尾部
    workInProgressHook = workInProgressHook.next = hook;
  }
  // 返回当前的 hook
  return workInProgressHook;
}

Update:

PreviousNew FeaturesNextSimple code

Last updated 2 years ago

Was this helpful?