• Hoot新特性


    特性State Hook

    components/Demo1.jsx

    import React, {useState} from "react";
    
    // export default class Demo1 extends React.Component{
    //   state = {
    //     count: 0
    //   }
    //   render(){
    //     return(
    //       <div>
    //         Hello class Hook:{this.state.count}
    //       </div>
    //     )
    //   }
    // }
    
    // function Demo1(){
    //   return(
    //     <div>
    //       Hello function Hook
    //     </div>
    //   )
    // }
    // export default Demo1;
    
    const Demo1 = () => {
      /**
       * count: 状态
       * setCount: setState -> setCount修改状态
       * useState(0): 默认值
       */
      const [count, setCount] = useState(10);
      const [page, setPage] = useState(0);
      return(
        <div>
          Hello function Hook:{ count } -- { page }
          <button onClick={ () => { setCount(count + 1);setPage(count + 1) }}>Add</button>
        </div>
      )
    }
    
    export default Demo1;
    

    特性Effect Hook

    components/Demo1.jsx

    // import React from "react";
    
    // export default class Demo2 extends React.Component{
    //   state = {
    //     count: 0
    //   }
    
    //   componentDidMount(){
    //     document.title = `You clicked ${this.state.count} times`
    //   }
    
    //   componentDidUpdate(){
    //     document.title = `You clicked ${this.state.count} times`
    //   }
    
    //   render(){
    //     return(
    //       <div>
    //         Hello Demo2: {`You clicked ${this.state.count} times`}
    //         <button onClick={() => {this.setState({count:this.state.count += 1})}}>Add</button>
    //       </div>
    //     )
    //   }
    // }
    
    import React, {useState, useEffect } from "react";
    
    const Demo2 = () => {
      const [count,setCount] = useState(0);
    
      /**
       * useEffect:
       *    componentDidMount
       *    componentDidMount
       *    componentWillUnmount
       */
      useEffect(() => {
        document.title = `You clicked ${count} times`
      });
    
      return(
        <div>
          Hello Demo2: {`You clicked ${count} times`}
          <button onClick={() => {setCount(count + 1)}}>Add</button>
        </div>
      )
    }
    export default Demo2;
    

    State Hook和Effect Hook实例

    components/Demo3/User.jsx

    // import React from 'react';
    
    // const userSet = ['张三', '李四', '王五', '赵六'];
    
    // export default class UserGenerator extends React.Component{
    //   state = {
    //     user: userSet[0]
    //   }
    
    //   generateUser = () => {
    //     let randomIndex = Math.floor(Math.random() * userSet.length);
    //     let randomUser = userSet[randomIndex];
    
    //     this.setState({
    //       user: randomUser
    //     })
    //   }
    
    //   render () {
    //     return (
    //       <div>
    //         <span>{this.state.user}</span>
    //         <button onClick={this.generateUser}>切换</button>
    //       </div>
    //     )
    //   }
    // }
    
    import React, { useState } from 'react';
    
    const userSet = ['张三', '李四', '王五', '赵六'];
    
    const UserGenerator = () => {
      const [user, setUser] = useState(userSet[0])
    
      const generateUser = () => {
        let randomIndex = Math.floor(Math.random() * userSet.length);
        let randomUser = userSet[randomIndex];
    
        setUser(randomUser)
      }
    
      return (
        <div>
          <span>{user}</span>
          <button onClick={generateUser}>切换</button>
        </div>
      )
    }
    
    export default UserGenerator;
    

    components/Demo3/Token.jsx

    import React, { useState, useEffect } from "react";
    
    class TokenForm extends React.Component{
      handlerSubmit = (event) => {
        event.preventDefault();
        // 数据来源props
        const { setToken } = this.props;
        const token = this.tokeenInput.value;
        if (token) {
          setToken(token)
        }
      }
    
      render () {
        return (
          <form onSubmit={this.handlerSubmit}>
            <input type="text" name="token" placeholder="enter your token" ref={input => {this.tokeenInput = input}} />
          </form>
        )
      }
    }
    
    // export default class TokenApp extends React.Component{
    //   state = {
    //     token: null
    //   }
    
    //   componentDidMount () {
    //     // 数据存在本地
    //     this.setState({ token: sessionStorage.getItem("token") });
    //   }
    
    //   setToken = token => {
    //     sessionStorage.setItem("token", token);
    //     this.setState({ token });
    //   }
    
    //   render () {
    
    //     const { token } = this.state;
    
    //     return (
    //       <div>
    //         <h1>Hello</h1>
    //         {token ? token : <TokenForm setToken={this.setToken} />}
    //       </div>
    //     )
    //   }
    // }
    
    const TokenApp = () => {
      const [token, setToken] = useState(sessionStorage.getItem("token"));
      useEffect(() => {
          sessionStorage.setItem("token", token);
      })
    
      return (
        <div>
          <h1>Hello</h1>
          {token ? token : <TokenForm setToken={setToken} />}
        </div>
      )
    }
    
    export default TokenApp;
    

    特性Hook TodoList

    components/Demo4/TodoForm.jsx

    // import React,{useState} from 'react';
    
    // const TodoForm = () => {
    //   const [value,setValue] = useState("");
    
    //   return(
    //     <div>
    //       <input type="text" value={value} onChange={(e) => setValue(e.target.value)} />
    //     </div>
    //   )
    // }
    
    // export default TodoForm;
    
    // https://github.com/rehooks/awesome-react-hooks
    
    import React,{useState} from "react";
    
    const useInputValue = (initialValue) => {
      const [value,setValue] = useState(initialValue);
    
      return{
        value,
        onChange: e => setValue(e.target.value),
        resetValue: () => setValue("")
      }
    }
    
    const TodoForm = ({onSubmit}) => {
      const {resetValue, ...text} = useInputValue("");
    
      const onSubmitHandler = (e) => {
        e.preventDefault();
        onSubmit(text.value);
        resetValue(); //清空输入框
      }
    
      return(
        <form onSubmit={onSubmitHandler}>
          <input type="text" {...text} />
        </form>
      )
    }
    
    export default TodoForm;
    

    components/Demo4/TodoList.jsx

    import React,{useState} from 'react';
    import TodoForm from './TodoForm';
    
    const TodoList = () => {
      /**
       * todolist是一个列表:数组
       */
      const [todos,setTodos] = useState([]);
    
      const setValue = (text) => {
        // 数组的合并
        /**
         * a = [1,2,3]
         * b = [4,5,6]
         * c = 7
         * [...a,...b,c]
         */
        setTodos([{text},...todos]);
        console.log(todos);
      }
    
      return(
        <div>
          <TodoForm onSubmit={setValue} />
          <div>
            {
              todos.map((element,index) => {
                console.log(element);
                return (
                  <div key={index}>
                    {element.text}
                  </div>
                )
              })
            }
          </div>
          <button onClick={() => {setTodos([])}}>clear</button>
        </div>
      )
    }
    
    export default TodoList;
    

    Hook Effect性能优化

    components/Demo5.jsx

    // import React from "react";
    
    // export default class Demo5 extends React.Component{
    //   state = {
    //     count: 0,
    //     name: "iwen"
    //   }
    
    //   componentDidMount(){
    //     document.title = `you clicked ${this.state.count} times`;
    //   }
    
    //   // componentDidUpdate(){
    //   //   console.log("触发");
    //   //   document.title = `you clicked ${this.state.count} times`;
    //   // }
    
    //   // 优化
    //   componentDidUpdate(prevProps, prevState){
    //     if(prevState.count !== this.state.count){
    //       console.log("触发");
    //       document.title = `you clicked ${this.state.count} times`;
    //     }
    //   }
    
    //   clickCountHandler = () => {
    //     this.setState({
    //       count: this.state.count + 1
    //     })
    //   }
    
    //   clickNameHandler = () => {
    //     this.setState({
    //       name: 'ime'
    //     })
    //   }
    
    //   render(){
    //     return(
    //       <div>
    //         <p>{`you clicked ${this.state.count} times`}</p>
    //         <p>{this.state.name}</p>
    //         <button onClick={this.clickCountHandler}>click count</button>
    //         <button onClick={this.clickNameHandler}>click name</button>
    //       </div>
    //     )
    //   }
    // }
    
    import React,{useState,useEffect} from "react";
    
    const Demo5 = () => {
      const [count,setCount] = useState(0);
      const [name,setName] = useState('iwen');
    
      // useEffect(() => {
      //   console.log("执行");
      //   document.title = `you clicked ${count} times`;
      // })
    
      // 优化
      /**
       * 第二个参数:
       * []:相当于生命周期函数的:componentDidMount
       * 没有第二个参数:相当于生命周期函数:componentDidMount  componentDidUpdate
       * [count]: 只监听count发生改变的时候,才会触发componentDidUpdate
       * 
       * return: 相当于componentWillMount
       */
      useEffect(() => {
        console.log("执行");
        document.title = `you clicked ${count} times`;
      },[count]);
    
      return(
        <div>
          <p>Your cliced {count} times</p>
          <p>{name}</p>
          <button onClick={() => setCount(count + 1)}>Click Count</button>
          <button onClick={() => setName('ime')}>Click name</button>
        </div>
      )
    }
    
    export default Demo5;
    

    特性--网络请求

    components/Demo6.jsx

    import React, { useState, useEffect } from "react";
    
    const useFetch = (url) => {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(true);
    
      useEffect(() => {
        (async () => {
          const response = await fetch(url);
          const data = await response.json();
          console.log(data);
          setData(data);
          setLoading(false);
        })();
      }, []);
    
      return { data, loading }
    }
    
    const Demo6 = () => {
      // const [data, setData] = useState(null);
      // const [loading, setLoading] = useState(true);
    
      // useEffect(() => {
      //   (async () => {
      //     const response = await fetch("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php");
      //     const data = await response.json();
      //     console.log(data);
      //     setData(data);
      //     setLoading(false);
      //   })();
      // })
    
      const { data, loading } = useFetch("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php");
    
      return (
        <div>
          {loading ? <div>...loading</div> : data.chengpinDetails[0].title}
        </div>
      )
    }
    
    export default Demo6;
    

    Hook useEffect实例

    components/Demo7.jsx

    // import React from "react"
    
    // export default class GithubListClass extends React.Component {
    //   constructor(props) {
    //     super(props);
    //     this.state = {
    //       page: 1,
    //       commits: []
    //     };
    //     this.nextPage = this.nextPage.bind(this);
    //     this.firstPage = this.firstPage.bind(this);
    //   }
    
    //   nextPage () {
    //     this.setState({ page: this.state.page + 1 }, () => this.loadGithubCommits());
    //   }
    
    //   firstPage () {
    //     this.setState({ page: 1 }, () => this.loadGithubCommits());
    //   }
    
    //   loadGithubCommits () {
    //     const { page } = this.props;
    //     fetch(`https//api.github.com/search/commits?q=repo:facebook/react+css&page=${page}`, {
    //       method: 'GET',
    //       headers: new Headers({ "Accept": "application/vnd.github.cloak-preview" }),
    //     })
    //       .then(data => data.json())
    //       .then(response => setCommits(response.items))
    //       .catch(error => console.log(error))
    //   }
    
    //   componentDidMount () {
    //     this.loadGithubCommits();
    //   }
    //   render () {
    //     return (
    //       <div>
    //         {this.state.commits.length !== 0 && <button onClick={this.nextPage}>next page</button>}
    //         {this.state.commits.length !== 0 && <button onClick={this.firstPage}>first page</button>}
    //         {
    //           this.state.commits.map(c => (
    //             <div key={c.sha}>
    //               {
    //                 c.commits && (
    //                   <div className="commit-container">
    //                     <p>{c.commits.committer.name}</p>
    //                     <p>{c.commits.message}</p>
    //                   </div>
    //                 )
    //               }
    //             </div>
    //           ))
    //         }
    //       </div>
    //     )
    //   }
    // }
    
    
    import React, { useState, useEffect } from 'react';
    
    const GithubListClass = () => {
      const [page, setPage] = useState(1);
      const [commits, setCommits] = useState([]);
    
      const nextPage = () => {
        setPage(page + 1);
      }
    
      const firstPage = () => {
        setPage(1);
      }
    
      useEffect(() => {
        fetch(`https//api.github.com/search/commits?q=repo:facebook/react+css&page=${page}`, {
          method: 'GET',
          headers: new Headers({ "Accept": "application/vnd.github.cloak-preview" }),
        })
          .then(data => data.json())
          .then(response => setCommits(response.items))
          .catch(error => console.log(error))
      }, [page]);  //一直执行
    
      return (
        <div>
          {commits.length !== 0 && <button onClick={nextPage}>next page</button>}
          {commits.length !== 0 && <button onClick={firstPage}>first page</button>}
          {
            commits.map(c => (
              <div key={c.sha}>
                {
                  c.commits && (
                    <div className="commit-container">
                      <p>{c.commits.committer.name}</p>
                      <p>{c.commits.message}</p>
                    </div>
                  )
                }
              </div>
            ))
          }
        </div>
      )
    }
    
    export default GithubListClass;
    

    React Hook 规则

    components/Demo8.jsx

    import React, { useState, useEffect } from "react";
    
    // https://zh-hans.reactjs.org/docs/hooks-rules.html
    
    const Demo8 = () => {
      const [count, setCount] = useState(0);
      useEffect(() => {
        if(count === 0){
          document.title = `ou clicked ${count} times`;
        }
        
      })
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>Click me</button>
        </div>
      )
    }
    
    export default Demo8;
    

    useEffect中的componentWillUnmount(副作用)

    components/Demo9

    import React, { Component, useState, useEffect } from 'react';
    
    const MyAPI = {
      count: 0,
      subscribe (cb) {
        this.intervalId = setInterval(() => {
          this.count += 1;
          cb(this.count)
        },1000)
      },
      unSubscribe () {
        clearInterval(this.intervalId);
        this.reset();
      },
      reset () {
        this.count = 0;
      }
    }
    
    // export default class Demo9 extends Component{
    //   state = {
    //     count: 0
    //   }
    
    //   componentDidMount () {
    //     MyAPI.subscribe(count => {
    //       this.setState({
    //         count: count
    //       })
    //     })
    //   }
    
    //   componentWillUnmount () {
    //     // 清楚定时器
    //     MyAPI.unSubscribe();
    //   }
    
    //   render () {
    //     return (
    //       <div>
    //         {this.state.count}
    //       </div>
    //     )
    //   }
    // }
    
    const Demo9 = () => {
      const [count, setCount] = useState(0);
    
      /**
       * 只在最顶层使用 Hook
       *    不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们
       * 只在 React 函数中调用 Hook
       *    不要在普通的 JavaScript 函数中调用 Hook。
       */
      useEffect(() => {
        MyAPI.subscribe(currentCount => {
          setCount(currentCount);
        })
    
        // 副作用的处理方式
        return () => {
          // 清除定时器
          MyAPI.unSubscribe();
        }
      }, [])
    
      return (
        <div>{count}</div>
      )
    }
    
    export default Demo9;
    

    React.memo特性

    components/Demo10/MemoDemo.jsx

    import React from 'react';
    import Child from './Child'
    
    /**
     * 注意
     * React.PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较。
    如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果。
    仅在你的 props 和 state 较为简单时,才使用 React.PureComponent,
    或者在深层数据结构发生变化时调用 forceUpdate() 来确保组件被正确地更新。
    你也可以考虑使用 immutable 对象加速嵌套数据的比较。
    此外,React.PureComponent 中的 shouldComponentUpdate() 将跳过所有子组件树的 prop 更新。
    因此,请确保所有子组件也都是“纯”的组件。
     */
    export default class MemoDemo extends React.PureComponent{
      state = {
        time: new Date()
      }
    
      componentDidMount () {
        setInterval(() => {
          this.setState({
            time: new Date()
          })
        }, 1000);
      }
    
      render(){
        console.log('render');
        return(
          <div>
            <Child seconds={1}/>
            {this.state.time.toString()}
          </div>
        )
      }
    }
    

    components/Demo10/Child.jsx

    import React from 'react';
    
    const Child = ({ seconds }) => {
      console.log('Child render');
    
      return <p>current time: {seconds}</p>
    }
    /**
     * React.memo 为高阶组件。
    如果你的组件在相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,
    以此通过记忆组件渲染结果的方式来提高组件的性能表现。
    这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。
     */
    export default React.memo(Child);
    

    App.js

    import logo from './logo.svg';
    import Demo1 from "./components/Demo1"
    import Demo2 from "./components/Demo2"
    import User from "./components/Demo3/User"
    import Token from "./components/Demo3/Token"
    import Demo5 from "./components/Demo5"
    import Demo6 from "./components/Demo6"
    import Demo7 from "./components/Demo7"
    import Demo8 from "./components/Demo8"
    import Demo9 from "./components/Demo9"
    import Demo10 from "./components/Demo10/MemoDemo"
    import TodoList from "./components/Demo4/TodoList"
    
    function App () {
      return (
        <div className="App">
          <Demo1 />
          <Demo2 />
          <User />
          <Token /> 
          <TodoList />
          <Demo5 />
          <Demo6 />
          <Demo7 />
          <Demo8 />
          <Demo9 />
          <Demo10 />
        </div>
      );
    }
    
    export default App;
    

    持续更新......

  • 相关阅读:
    JavaScript 的核心机制——event loop(最易懂版)
    关于敏捷讨论的感想
    前端,如何更优雅的面对异步
    广告行业中那些趣事系列10:推荐系统中不得不说的DSSM双塔模型
    书中自有黄金屋系列7:读《博世宁医学通识讲义》
    广告行业中那些趣事系列9:一网打尽Youtube深度学习推荐系统
    书中自有黄金屋系列6:读《浪潮之巅》-下篇
    书中自有黄金屋系列6:读《浪潮之巅》-上篇
    广告行业中那些趣事系列8:详解BERT中分类器源码
    书中自有黄金屋系列5:读《正面管教》
  • 原文地址:https://www.cnblogs.com/lhongsen/p/14534749.html
Copyright © 2020-2023  润新知