[React] Hook

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

const [FLG1, setFLG1] = useState(true)
const [FLG2, setFLG2] = useState(true)

////////////////////////////////////////
// useEffect 啥时用?
// -> 有一些处理不想让它每次组件渲染时都执行
// -> 异步调用时执行
////////////////////////////////////////
/*
useEffect(() => {
  console.log("Home.useEffect")
});
// }, []);
// }, [FLG1]);
*/
View Code

 

 

Ajax 从后端取数据。与服务器端保持长链接,比如股票行情图。

通过一个按钮函数,从而触发useEffect,对“长链接”进行结束操作~

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

const Home = () => {

    const [time, updateTime] = useState(Date.now());
    const [searchCondition, setSearchCondition] = useState("游戏")
    const [newsContent, setNewsContent] = useState("")

    useEffect(() => {
        setNewsContent(`${searchCondition}新闻:${Math.random().toString()}\n${newsContent}`);   // 不断地追加显示的内容~
        const timeoutId = setTimeout(() => updateTime(Date.now()), 3000);
        return () => {
            clearTimeout(timeoutId);
        }
    }, [time]);

    useEffect(() => {
        /////////////////////////////////////////////
        // cleanup 就看这里,其他的不要看
        return () => {
            console.log(searchCondition, "cleanup")
        }
        /////////////////////////////////////////////
    }, [searchCondition]);

const btn_search_click = () => { const category = ["游戏", "军事", "股票", "美食", "体育"]; const newCategory = category[Math.floor(Math.random() * category.length)]; setNewsContent("") setSearchCondition(newCategory); }
return (
<React.Fragment> <h1>Home</h1> <h2 className="text-success">显示条件: {searchCondition.toString()}</h2> <div className="p-1"> <button onClick={btn_search_click} className="btn btn-primary btn-lg mx-1">检索</button> </div> <hr /> <pre className="text-secondary"> {newsContent} </pre> </React.Fragment> ) } export default Home;

 

 

useContext

createContext是个特殊的标签,可以将value中的内容提供给该标签下子组件们 instead of props。

# App.js

import React, { createContext, useState } from 'react' import { Route, Switch, Redirect } from 'react-router-dom'; import Header from './components/Header'; import Home from './pages/Home'; import About from './pages/About'; // 创建上下文对象 export const DeeplearnAWSContext = createContext() function App() {
// 创建上下文数据对象 const [deeplearnAWS, setDeeplearnAWS] = useState({ sitename: '深学AWS', author: 'Koma', sayHelo: (pname) => { console.log(`Helo ${pname}. ${Math.random().toString()}`) } }) return (
<div> <Header></Header> <div className="p-4"> {/* 提供上下文数据 */} <DeeplearnAWSContext.Provider value={deeplearnAWS}> <Switch> <Route path="/" exact> <Redirect to="/home"></Redirect> </Route> <Route path="/home"> <Home></Home> </Route> <Route path="/about"> <About></About> </Route> </Switch> </DeeplearnAWSContext.Provider> </div> </div> ); } export default App;

在子组件中,获得参数。

import React, { useContext } from 'react'

// 引入上下文对象
import { DeeplearnAWSContext } from '../App';

const About = () => {
    // 实例化上下文对象
    const DeeplearnAWS = useContext(DeeplearnAWSContext)

    console.log(DeeplearnAWS)

    return (
        <React.Fragment>
            <h1>About</h1>
            <hr />
            {/* 使用上下文数据 */}
            <h2>sitename: {DeeplearnAWS.sitename}</h2>
            <h3>author: {DeeplearnAWS.author}</h3>
            <button className="btn btn-success" onClick={() => DeeplearnAWS.sayHelo("React")}>SayHelo</button>
        </React.Fragment>
    )
}

export default About;

 

 

useReducer

复杂状态管理。比 useState 更好~

onClick 方法调用  dispatch改变useReducer对应的 状态count。

import React, { useReducer } from 'react'

const Clicker = () => {
const [count, dispatch] = useReducer( (count, action) => { // 本函数应该返回新的 count 值 console.log(count, action) switch (action) { case "add": return count + 1 case "minus": return count - 1 default: return 100 } }, 100) return (
<React.Fragment> <h1>Clicker</h1> <hr /> <h2 className={count < 100 ? "text-danger" : "text-dark"}>{count}</h2> <div className="py-2 bg-light"> <button className="btn btn-primary mx-1" onClick={() => { dispatch("add") }}>加击一次</button> // dispatch 的参数比较简洁 <button className="btn btn-success mx-1" onClick={() => { dispatch("minus") }}>减击一次</button> </div> <hr /> <div className="py-2 bg-light"> <button className="btn btn-info mx-1" onClick={() => { dispatch("下回分解") }}>加击10次</button> <button className="btn btn-warning mx-1" onClick={() => { dispatch("下回分解") }}>减击10次</button> </div> </React.Fragment> ) } export default Clicker;

控制加减的次数,那就增强 dispatch 的参数:action to { type: "add", step: 10 }

也可以是一个dict,具体看如下代码示范。

import React, { useReducer } from 'react'

const Clicker = () => {
    const [count, dispatch] = useReducer((count, action) => {
        // 本函数应该返回新的 count 值
        console.log(count, action)
        switch (action.type) {
            case "add":
                return count + action.step
            case "minus":
                return count - action.step
            default:
                return 100
        }
    }, 100)

    return (
        <React.Fragment>
            <h1>Clicker</h1>
            <hr />
            <h2 className={count < 100 ? "text-danger" : "text-dark"}>{count}</h2>
            <div className="py-2 bg-light">
                <button className="btn btn-primary mx-1" onClick={() => {
                    dispatch({
                        type: "add",
                        step: 1
                    })
                }}>加击一次</button>
                <button className="btn btn-success mx-1" onClick={() => {
                    dispatch({
                        type: "minus",
                        step: 1
                    })
                }}>减击一次</button>
            </div>
            <hr />
            <div className="py-2 bg-light">
                <button className="btn btn-info mx-1" onClick={() => {
                    dispatch({
                        type: "add",
                        step: 10
                    })
                }}>加击10次</button>
                <button className="btn btn-warning mx-1" onClick={() => {
                    dispatch({
                        type: "minus",
                        step: 10
                    })
                }}>减击10次</button>
            </div>
        </React.Fragment>
    )
}

export default Clicker;
View Code

 

 

useMemo

感觉,这个比较常用,属于一种常规优化。

通过”状态 FLG2" 过度一下,再经过 useMemo控制“渲染的变量“。

import React, { useState, useMemo } from 'react'

import Header from './components/Header';

function App() {
    console.log("----- App.js run -----")

    const [FLG, setFLG] = useState(false)
    const [FLG2, setFLG2] = useState(false)

    // 每次渲染执行,通过大量计算,得出AI结果
    const AIResult = () => {
        console.log("AI Running...")
        var result = 0
        for (var i = 1; i <= 100; i++)
            result += i;
        return result
    }

    // 只有当 FLG2 改变时才执行
    const AIResult2 = useMemo(() => {
        console.log("AI2 Running...")
        var result = 0
        for (var i = 1; i <= 100; i++)
            result += i;
        return result
    }, [FLG2])

    return (
        <div>
            <Header></Header>
            <div className="p-4">
                <div className="fs-1">{FLG.toString()}, {FLG2.toString()}</div>
                <div>
                    <button className="btn btn-success" onClick={() => setFLG(!FLG)}>更新标记</button>
                    <button className="btn btn-info mx-1" onClick={() => setFLG2(!FLG2)}>更新标记2</button>
                </div>
                <hr />
                <h3>AI :{AIResult().toString()}</h3>
                <h3>AI2:{AIResult2.toString()}</h3>
            </div>
        </div>
    );
}

export default App;

 

 

useFetch

需要单独安装下这个包。 

$ npm install use-http --save
$ npm start

 

如下,点击某个按钮,读服务端数据,获得相应的列表并显示。

 

import React, { useState, useEffect } from 'react'
import useFetch from 'use-http'    // 单独安装的包以支持

import Header from './components/Header';

function App() {
    console.log("----- App.js run -----")

    const { get, post, response, loading, error } = useFetch('https://swapi.dev/api')
    const [dataset, setDataset] = useState([])

    // 启动装载
    useEffect(() => { search('films') }, [])

    async function search(presource) {
        console.log("search", presource)
        const datalist = await get('/' + presource)
        if (response.ok) setDataset(datalist.results)
        else setDataset([])
    }

    const btn_click = async (pvalue) => {
        await search(pvalue)
    }

    return (
        <div>
            <Header></Header>
            <div className="p-4">
                <h1 className="border-bottom">useFetch</h1>
                <div>
                    <button className="btn btn-success mx-1" onClick={() => btn_click("films")}>电影</button>
                    <button className="btn btn-primary mx-1" onClick={() => btn_click("starships")}>飞船</button>
                    <button className="btn btn-info mx-1" onClick={() => btn_click("people")}>人物</button>
                    <button className="btn btn-warning mx-1" onClick={() => btn_click("aws")}>AWS</button>
                </div>
                <hr />
                <div>
                    {dataset.map((item, index) => (
                        < div key={index} > {index + 1}. {item.title || item.name}</div>
                    ))}
                </div>
            </div>
        </div >
    );
}

export default App;

 

 

useInput

处理表单输入,可顺便参考下:[React] Review

需要安装 React Hooks:

$ npm install rooks --save

 
React Hooks 是 对React function 组件的一种扩展,通过一些特殊的函数,让无状态组件拥有状态组件才拥有的能力。 Hooks 是React 函数组件中的一类特殊函数,通常以use 开头。
 
(类似vue的双向绑定)

如果一个表格中需要多个输入,则定义多个 useInput 即可。

import React, { useState } from 'react';
import { useInput } from "rooks";

import Header from './components/Header';

function App() {
    const inputUserName = useInput("koma");   // 可见默认值是个"koma"

    console.log(inputUserName)

    return (
        <div>
            <Header></Header>
            <div className="py-2 px-4">
                <h1>React Rooks</h1>
                <form class="row g-3">
                    <div class="col-6">
                        <input className="form-control" {...inputUserName} />     // 这里写入后,自动触发并渲染~
                    </div>
                    <div class="col-auto">
                        <button type="button" class="btn btn-primary" onClick={() => { alert(inputUserName.value) }}>确认</button>
                    </div>
                </form>
                <p>
                    输入内容: <b>{inputUserName.value}</b>
                </p>
            </div>
        </div>
    );
}

export default App;

 

posted @ 2023-05-29 21:46  郝壹贰叁  阅读(12)  评论(0编辑  收藏  举报