React函数式组件-自定义hooks

自定义React hooks

回顾一下React常用hooks
React hooks中除了常用的useStateuseEffectuseRef
我们还可以自定义hooks,可以达到不增加组件而实现组件之间的一些复用的目的。

在子组件中,可以获取父级传来的值,也可以对值进行修改。

子组件Child.js

import React, { useState, useEffect, useRef } from 'react';
export default function Child(props) {
    let { data } = props;//接收父组件传来的数据
    
    //只要不修改ref,就会存储初始值(变化之前的值)
    let [age, setAge] = useState(0);
    //绑定dom
    //let currentAge = useRef();
    //下面的代码是将每次变化后的age值,传入useRef(),
    //这样一来就只是对数据进行操作,绑定的是数据而不是具体的dom了
    let currentAge = useRef(age);
    useEffect(() => {
        // 绑定的dom
        //点击按钮“长一岁”,此时控制台输出的是绑定的标签及其包含的内容
        //控制台输出如下: 
        // 

0

//

1

// ...... console.log(currentAge.current); // currentAge.current初始值, age是存变化后的值 console.log(currentAge.current, age); // 把每次变化后的age值,再赋给当前值curAge.current,即变化前的值 currentAge.current = age; // 绑定了数据,不再是dom // 每次变化后的值赋值给了当前值,此时点击按钮“长一岁”时控制台输出内容都是数据,而不是标签了 // 0 // 0 1 // 1 // 1 2 // 2 // ... }, [age]); let [txt, setTxt] = useState("today is sunny"); let txtAfter = useRef(txt); useEffect(() => { console.log(txtAfter.current,txt);//txt即是每次变化的值 txtAfter.current = txt; console.log(txtAfter); }, [txt]); return ( <div> <h2>name:{data.name}</h2> <h2 ref={currentAge}>age:{age}</h2> <button onClick={() => { setAge(++age) }}>长一岁</button> <p>{txt}</p> <input type="text" value={txt} onChange={({ target }) => { setTxt(target.value) }} /> </div> ); }

父组件App.js

import React, { useState, useEffect } from 'react';
import Child from './Child';
export default function App() {
   let [data, setData] = useState({
      name: "金毛",
      age: 3
   })
   let [show, setShow] = useState(true);
   return (
      <div>
         {show?<Child data={data} />:""}
         <button onClick={() => {
            setData({
               // 修改name值,age不变
               name: "泰迪",
               age: data.age
            })
         }}>
            点击切换
         </button>
         <button onClick={()=>{setShow({show:false})}}>
            卸载
         </button>
      </div>
   );
}

自定义hooks需注意

  • 以use开头,遵循驼峰命名法
  • 自定义hooks必须在React函数组件内调用

示例2
App.js

import React, { useEffect,useRef} from 'react';
import { useSize, useScrollY } from './myhooks'
export default function App() {
   let [scrollY,setScrollY] = useScrollY();//组件内使用useScrollY,必须在React函数组件内调用
   let newScrollY = useRef(scrollY);//绑定input框输入的数据
   // 监测鼠标滚动距离
   useEffect(()=>{
      window.onscroll=()=>{
         newScrollY.current = scrollY;//将每次改变的值赋给当前值,即滚动的最新值
         setScrollY(newScrollY.current);
      }
      return ()=>{
         window.onscroll = null;
      }
   },[scrollY]);
   return (
      <div>
         <ul>
            {  
               // 测试数据
               [...(".".repeat(100))].map((item, index) => {
                  return <li key={index}>{index + 1}条数据</li>
               })
            }
         </ul>
         <a onClick={() => { 
            // setScrollY(100); //调用此函数,点击跳到scrollY为100的位置  
            setScrollY(scrollY); //有input框输入的数值传入,如果想跳到哪个位置,直接输入对应的数值即可
         }} 
            style={{position:'fixed',left:'200px',top:'200px'}}>
            {scrollY}
         </a>
         {/* 添加一个input输入框,每次输入一个数值 */}
         <input type="text" value={scrollY} ref={newScrollY}
         onChange={({target})=>{setScrollY(target.value)}}
         style={{position:'fixed',left:'200px',top:'220px'}}
         />
      </div>
   );
}

myhooks.js

import React, { useState } from 'react';
// 自定义hooks
// 开头必须是use
function useSize() {
    return {
        w:window.innerWidth,
        h:window.innerHeight
    }
}
function useScrollY() {//获取和设置滚动条
    let [scrollY, setScrollY] = useState(window.scrollY);
    return [
        scrollY, //返回的值
        (newScrollY)=>{ //修改这个值的函数
            window.scrollTo(0,newScrollY);
            setScrollY(newScrollY);
        }
    ]
}
export {useSize,useScrollY};

你可能感兴趣的:(React,react,自定义hooks)