react hooks使用问题

117 阅读2分钟

react useContext useReducer≈redux

父组件

const intialState = { count: 0 }
const reducer = (state, action) => {
  switch(action.type) {
    case "ADD":
      return { ...state, count: action.count }
    default:
      return state
  }
}
export default () => {
  const Context = React.createContext(null)
  const [state, dispatch] = useReducer(reducer, intialState)
  return (
    <Context.Provider value={{ state, dispatch }}>
    	<Child Context={Context}/>
    </Context.Provider>
  )
}

子组件

export default ({ Context }) => {
  const { state, dispatch } = useReducer(Context)
  return (
    <div onClick={() => {
    	dispatch({ type: "ADD", payload:state.count + 1 })
  	}}>
    	{state.count}
    </div>
  )
}

setState批量更新在setTimeout函数中失效,导致useEffect设定函数执行两边

对于useReducer生成的dispatch事件的情况同样如此

特别注意lodash.debounce函数的使用,因为他的实现原理就是setTimeout

function App() {

  const [count, setCount] = useState(0)
  const [time, setTime] = useState(0)

  useEffect(() => {
    console.log(1111);
  }, [count, time])

  // 只打印一遍111
  const clickOne = () => {
    setCount(count + 1)
    setTime(time + 1)
  }

  // 打印两遍111,可以理解为App函数执行了两遍,因为这两个set都是建立了自己的函数执行空间
  const clickTwo = () => {
    setTimeout(() => {
      setCount(count + 1)
      setTime(time + 1)
    }, 1000)
  }

  // 还是打印两遍111,不理解
  const clickThree = () => {
    setTimeout(() => {
      const fn = () => {
        setCount(count + 1)
        setTime(time + 1)
      }
      fn()
    }, 1000)
  }

  return (
    <div>
      <div onClick={clickOne}>正常点击</div>
      <div onClick={clickTwo}>setTimeout点击</div>
      <div onClick={clickThree}>setTimeout合并set点击</div>
    </div>
  )
}

export default App

lodash.debounce在hooks中失效问题

使用useCallback缓存函数解决此问题

function App() {

  const [count, setCount] = useState(0)

  // 点击失效点击按钮时,如果中途执行过set方法,函数会重新执行一遍,生成一个新的clickOne函数
  // 那么此时的防抖就失效了,因为防抖需要保证的是函数永远是同一个,才能清除之前函数
  const clickOne = debounce(() => {
    console.log(1111);
  }, 3000)

  // 此时相当于缓存了clickTwo函数,此方法永远是同一个函数,不会在App函数执行过程中更新
  // 那么debounce就能生效
  const clickTwo = useCallback(debounce(() => {
      console.log(22222);
    }, 3000), [])

  const clickThree = () => {
    setCount(count + 1)
  }

  return (
    <div>
      <br />
      <div onClick={clickOne}>失效点击</div>
      <div onClick={clickTwo}>生效debounce点击</div>
      <div onClick={clickThree}>辅助测试点击{count}</div>
    </div>
  )
}

条件渲染

在 JavaScript 中,true && expression 总是会返回 expression, 而 false && expression 总是会返回 false。

因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。

请注意,返回 false 的表达式会使 && 后面的元素被跳过,但会返回 false 表达式。在下面示例中,render 方法的返回值是 

0

render() {
  const count = 0;
  return (
    <div>
      { count && <h1>Messages: {count}</h1>}
    </div>
  );
}