React Hooks上手

56 阅读1分钟

React Hooks上手

1、自定义hooks

  • demo[useTitle]
import React, { Component, useState, useEffect } from "react";

export const useTitle = (title) => {  
  useEffect(() => {    
    document.title = title;  
  }, [title]);
};

function Counter() {  
  const [count, setCount] = useState(0);  
  const incrementCount = () => setCount(count + 1);  
  useTitle(`You clicked ${count} times`);  
  return (    
    <div>      
      <p>You clicked {count} times</p>      
      <button onClick={incrementCount}>Click me</button>    
    </div> 
  );
}
export default Counter;
  • demo[useBoolean]
import { useCallback, useState } from "react";
export const useBoolean = initial => {  
  const [value, setValue] = useState(initial);  
  return {    
    value,    
    setValue,    
    toggle: useCallback(() => setValue(v => !v)),    
    setTrue: useCallback(() => setValue(true)),    
    setFalse: useCallback(() => setValue(false))  
  };
};
const App = () => {    
  const showCounter = useBoolean(true);    
  return (        
    <div>            
      { showCounter.value ? <h3>Hello</h3> : null }            
      <button onClick={showCounter.toggle}>Toggle</button>        
    </div>   
  )
}
export default App;  
  • demo[useArray]
import { useCallback, useState } from "react";  

export const useArray = initial => {    
  const [value, setValue] = useState(initial);    
  return {      
    value,      
    setValue,      
    add: useCallback(a => setValue(v => [...v, a])),      
    clear: useCallback(() => setValue(() => [])),      
    removeById: useCallback(id => setValue(arr => arr.filter(v => v && v.id !== id))),      
    removeIndex: useCallback(index => setValue(v => {v.splice(index, 1); return v; })) 
  }; 
};  
export const App = () => {      
  const todos = useArray(["hi there", "sup", "world"]);      
  return (        
    <div>          
      <h3>Todos</h3>          
      <button onClick={() => todos.add(Math.random())}> add </button>          
      <ul>            
        { todos.value.map((todo, i) => (              
          	<li key={i}> {todo}                
            <button onClick={() => todos.removeIndex(i)} >delete</button>  
            </li>            
        	))
        }          
      </ul>          
      <button onClick={todos.clear}> clear todos </button>        
    </div>      
  )    
}
  • demo[useFormInfo]
import { useCallback, useState } from "react";

export const useFormInfo = (initial) => {
  const [value, setParams] = useState(initial);
  return {
    value,
    setParams,
    setFiled: useCallback((filed) => (current) => setParams((prev) => ({ ...prev, [filed]: current }))),
    setTargetFiled: useCallback((filed) => (e) => setParams((prev) => ({ ...prev, [filed]: e.target?.value }))),
    removeFiled: useCallback((filed) => setParams((prev) => delete prev[filed] && prev))
  };
};

const getInitial = () => ({
  refuseType: null,
  refuseReason: null,
  name: null
});

export const App = () => {
    const refuseInfo = useFormInfo(getInitial());
    return (
        <div>
            <Select
              labelInValue
              placeholder="请选择理由"
              onChange={refuseInfo.setFiled("refuseType")}
              options={REFUSE_TYPE_OPTIONS}
            />
            <div className="InputBox">
              <Input.TextArea
                rows={2}
                placeholder="输入拒绝理由"
                showCount
                maxLength={15}
                onChange={refuseInfo.setTargetFiled("refuseReason")}
              />
              <Input onChange={refuseInfo.setTargetFiled("name")} />
            </div>
            <div>
              <Button onClick={() => {
                // refuseInfo.removeFiled('name')
                console.log(refuseInfo.value)
              }}>提交</Button>
            </div>
        </div>
    )
}

2、useState、useEffect

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

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

// const [count] = useState(0); // 或者
useEffect(() => {
  document.title = `You clicked ${count} times`;
},[count]);

3、useRef、forwardRef、useImperativeHandle

  import React, { useRef, useEffect, forwardRef, useImperativeHandle } from "react";

  forwardRef(function InputCom({ref}) {
    const [open, setOpen] = useState(false)
    const [name, setName] = useState(null)
    useImperativeHandle(ref, ()=>{
        return {
            show: () => {
              setOpen(true)
            },
            getValue:()=>{
              return ref.current.value||name
            }
        }
    })
    
    return (
      <div>
        <input 
          value={name} 
          type='text' 
          ref={ref} 
          onChange=(e=>setName(e.target.value)) 
        />
        <Modal open={open}>
              code
        </Modal>
      </div>
    )
  })
  
  function App() {
    const inpRef = useRef(null)
  
    const focus = () => {
      inpRef.current?.focus()
    }
    
    const openInput = () => {
        inpRef.currnet.show()
    }
  
    return (
      <div onClick ={openInput} >
        <InputCom ref={inpRef}  />
      </div>
    )
  }

4、useReducer

  • 方案1
import React, { useState } from 'react'

const getInitial = () => ({
  refuseType: null,
  refuseReason: null,
  name: null,
})

const Page: React.FC<IProps> = (props)=> {
  const [refuseInfo, setRefuseInfo] = useState(getInitial())
  
  const onChange = (filed, value) => {
        return (current)=>{
            setRefuseInfo((prev) => {
                return {
                    ...prev,
                    [filed]: current?.target?.value ? current.target.value : current;
                }
            })
        }
  }
  
  const getValue = () => refuseInfo
  // refuseType, refuseReason, name
  
  return (
    <div classNmae="pageWrapper">
      <Select
        labelInValue
        placeholder="请选择理由"
        onChange={onChange('refuseType')}
        options={REFUSE_TYPE_OPTIONS}
      />
      <div className={stl.InputBox}>
        <Input.TextArea 
          ref={reasonRef} 
          rows={2} 
          placeholder='输入拒绝理由' 
          showCount 
          maxLength={15} 
          onChange={onChange('refuseReason')} 
        />
        <Input value={user.name} onChange={onChange('name')} />
      </div>
    </div>
  )
}
  • 方案2
import React, { useReducer } from 'react'

const getInitial = () => ({
  refuseType: null,
  refuseReason: null,
})

const formReducer = (state: any, action: { type: any; value: any }) => {
  switch (action.type) {
    case 'refuseType':
      return {
        ...state,
        refuseType: action.value,
      }
    case 'refuseReason':
      return {
        ...state,
        refuseReason: action.value
      }
    default:
      return state
  }
}

const Page: React.FC<IProps> = (props)=> {
  const [state, dispatch] = useReducer(formReducer, getInitial())
  
  const getValue = () => state
  // refuseType, refuseReason
  
  return (
    <div classNmae="pageWrapper">
      <Select
        labelInValue
        placeholder="请选择理由"
        onChange={(value)=>dispatch({ type: 'refuseType', value: value.value})}
        options={REFUSE_TYPE_OPTIONS}
      />
      <div className={stl.InputBox}>
        <Input.TextArea 
          ref={reasonRef} 
          rows={2} 
          placeholder='输入拒绝理由' 
          showCount 
          maxLength={15} 
          onChange={(e)=>dispatch({ type: 'refuseReason', value: e.target.value})} 
        />
      </div>
    </div>
  )
}

更多资料

以上内容仅是个人观点,欢迎大家点评修正。