차이점: 1. 후크는 클래스보다 더 간결하게 작성됩니다. 2. 후크의 비즈니스 코드는 클래스보다 더 집계됩니다. 3. 클래스 구성 요소의 논리 재사용은 일반적으로 렌더링 소품과 HOC를 사용하는 반면, 반응 후크는 논리를 재사용하기 위한 사용자 정의 후크를 제공합니다. .
이 튜토리얼의 운영 환경: Windows 7 시스템, 반응 버전 17.0.1, Dell G3 컴퓨터.
반응 후크와 클래스 구성 요소의 차이점은 무엇입니까? 반응 후크와 클래스 구성 요소를 비교하고 차이점에 대해 이야기해 보겠습니다.
함수 구성 요소는 자체 상태를 가질 수 없습니다. Hooks 이전에는 함수 구성 요소가 Stateless였으며 부모 구성 요소의 상태는 props를 통해 획득되었지만 Hook은 함수 구성 요소의 내부 상태를 유지하기 위해 useState를 제공합니다.
기능 컴포넌트에서는 컴포넌트의 수명주기를 모니터링할 수 없습니다. useEffect는 여러 수명주기 함수를 집계합니다.
클래스 구성 요소의 수명 주기는 더 복잡합니다(버전 15에서 버전 16으로 변경 사항이 큽니다).
클래스 구성 요소 로직은 재사용하기 어렵습니다(HOC, 렌더링 소품). 클래스와 비교 한 후크의 비교 (비교)
클래스 구성 요소를 사용할 때 함수가 두 개의 수명 주기 함수에 나타나는 경우가 종종 있습니다. 예:
class ExampleOfClass extends Component { constructor(props) { super(props) this.state = { count: 1 } } handleClick = () => { let { count } = this.state this.setState({ count: count+1 }) } render() { const { count } = this.state return ( <div> <p>you click { count }</p> <button onClick={this.handleClick}>点击</button> </div> ) } }
타이머 추가와 타이머 지우기는 서로 다른 두 가지 수명주기 기능에 있기 때문에 그 사이에 다른 비즈니스 코드가 많이 있을 수 있으므로 타이머 지우기가 추가되지 않은 경우 타이머 지우기를 잊어버릴 수 있습니다. 구성 요소가 제거되면 서버 기능으로 인해 메모리 누수 및 지속적인 네트워크 요청 등의 문제가 발생할 수 있습니다. 그러나 후크를 사용하면 코드를 더 중앙 집중화하고 관리하기 쉽게 만들 수 있으며 잊어버리기 쉽지 않습니다.
function ExampleOfHooks() { const [count, setCount] = useState(0) const handleClick = () => { setCount(count + 1) } return ( <div> <p>you click { count }</p> <button onClick={handleClick}>点击</button> </div> ) }
3. 로직 재사용이 편리합니다.
클래스 구성 요소의 로직 재사용은 일반적으로 렌더링 소품과 HOC를 사용합니다. React Hooks는 로직을 재사용하기 위한 사용자 정의 후크를 제공합니다.
let timer = null componentDidMount() { timer = setInterval(() => { // ... }, 1000) } // ... componentWillUnmount() { if (timer) clearInterval(timer) }
useEffect(() => { let timer = setInterval(() => { // ... }, 1000) return () => { if (timer) clearInterval(timer) } }, [//...])
구문
이 구문은 ES6 배열 구조이며, 배열의 첫 번째 값은 선언된 상태이고 두 번째는 각 값입니다. 상태를 바꾸는 함수이다.
import React, { Component } from 'react' class MousePosition extends Component { constructor(props) { super(props) this.state = { x: 0, y: 0 } } handleMouseMove = (e) => { const { clientX, clientY } = e this.setState({ x: clientX, y: clientY }) } componentDidMount() { document.addEventListener('mousemove', this.handleMouseMove) } componentWillUnmount() { document.removeEventListener('mousemove', this.handleMouseMove) } render() { const { children } = this.props const { x, y } = this.state return( <div> { children({x, y}) } </div> ) } } // 使用 class Index extends Component { constructor(props) { super(props) } render() { return ( <MousePosition> { ({x, y}) => { return ( <div> <p>x:{x}, y: {y}</p> </div> ) } } </MousePosition> ) } } export default Index
2.useEffect
const [value, setValue] = useState(0)
import React, { useEffect, useState } from 'react' function usePosition() { const [x, setX] = useState(0) const [y, setY] = useState(0) const handleMouseMove = (e) => { const { clientX, clientY } = e setX(clientX) setY(clientY) } useEffect(() => { document.addEventListener('mousemove', handleMouseMove) return () => { document.removeEventListener('mousemove', handleMouseMove) } }) return [ {x, y} ] } // 使用 function Index() { const [position] = usePosition() return( <div> <p>x:{position.x},y:{position.y}</p> </div> ) } export default Index
useEffect는 콜백 함수와 종속성을 전달받으며, 내부의 콜백 함수는 종속성이 변경될 때만 실행됩니다. useEffect는 클래스 구성 요소 didMount, didUpdate 및 willUnmount의 수명 주기 기능과 유사합니다.주의사항
useEffect의 콜백 함수는 부작용을 제거하거나
if를 반환하지 않는 처리 함수만 반환할 수 있습니다. useEffect가 전달됩니다. 종속성이 빈 배열이면 useEffect 내부 함수는 한 번만 실행됩니다
3. useMemo, useCallback
useMemo 및 useCallback은 주로 구성 요소 업데이트 수를 줄이고 구성 요소를 최적화하는 데 사용됩니다. 성능.
useMemo는 콜백 함수와 종속성을 전달받으며, 종속성이 변경된 경우에만 콜백 함수가 다시 실행됩니다.
useCallback은 콜백 함수와 종속성을 수신하고, 기억된 버전의 콜백 함수를 반환합니다. 기억된 버전은 종속성이 변경될 때만 다시 기억됩니다.
function Example() { const [val, setVal] = useState(0) const timeoutFn = () => { setTimeout(() => { // 取得的值是点击按钮的状态,不是最新的状态 console.log(val) }, 1000) } return ( <> <p>{val}</p> <button onClick={()=>setVal(val+1)}>+</button> <button onClick={timeoutFn}>alertNumber</button> </> ) }
우리는 일반적으로 클래스 컴포넌트에 대해 React.PureComponent를 사용합니다. PureComponent는 shouldUpdate에서 비교를 수행하여 함수 컴포넌트에 대해 업데이트가 필요한지 결정합니다. 우리는 일반적으로 React를 사용합니다. 메모. 하지만 React Hooks를 사용하면 각 렌더링 업데이트가 독립적이므로(새 상태가 생성됨) React.memo를 사용하더라도 여전히 다시 렌더링됩니다.
比如下面这种场景,改变子组件的name值后由于父组件更新后每次都会生成新值(addAge函数会改变),所以子组件也会重新渲染。
function Parent() { const [name, setName] = useState('cc') const [age, setAge] = useState(22) const addAge = () => { setAge(age + 1) } return ( <> <p>父组件</p> <input value={name} onChange={(e) => setName(e.target.value)} /> <p>age: {age}</p> <p>-------------------------</p> <Child addAge={addAge} /> </> ) } const Child = memo((props) => { const { addAge } = props console.log('child component update') return ( <> <p>子组件</p> <button onClick={addAge}>click</button> </> ) })
使用useCallback优化
function Parent() { const [name, setName] = useState('cc') const [age, setAge] = useState(22) const addAge = useCallback(() => { setAge(age + 1) }, [age]) return ( <> <p>父组件</p> <input value={name} onChange={(e) => setName(e.target.value)} /> <p>age: {age}</p> <p>-------------------------</p> <Child addAge={addAge} /> </> ) } const Child = memo((props) => { const { addAge } = props console.log('child component update') return ( <> <p>子组件</p> <button onClick={addAge}>click</button> </> ) })
只有useCallback的依赖性发生变化时,才会重新生成memorize函数。所以当改变name的状态是addAge不会变化。
useRef类似于react.createRef。
const node = useRef(initRef)
useRef 返回一个可变的 ref 对象,其 current 属性被初始化为传入的参数(initRef)
作用在DOM上
const node = useRef(null) <input ref={node} />
这样可以通过node.current属性访问到该DOM元素。
需要注意的是useRef创建的对象在组件的整个生命周期内保持不变,也就是说每次重新渲染函数组件时,返回的ref 对象都是同一个(使用 React.createRef ,每次重新渲染组件都会重新创建 ref)。
useReducer类似于redux中的reducer。
语法
const [state, dispatch] = useReducer(reducer, initstate)
useReducer传入一个计算函数和初始化state,类似于redux。通过返回的state我们可以访问状态,通过dispatch可以对状态作修改。
const initstate = 0; function reducer(state, action) { switch (action.type) { case 'increment': return {number: state.number + 1}; case 'decrement': return {number: state.number - 1}; default: throw new Error(); } } function Counter(){ const [state, dispatch] = useReducer(reducer, initstate); return ( <> Count: {state.number} <button onClick={() => dispatch({type: 'increment'})}>+</button> <button onClick={() => dispatch({type: 'decrement'})}>-</button> </> ) }
通过useContext我们可以更加方便的获取上层组件提供的context。
父组件
import React, { createContext, Children } from 'react' import Child from './child' export const MyContext = createContext() export default function Parent() { return ( <div> <p>Parent</p> <MyContext.Provider value={{name: 'cc', age: 21}}> <Child /> </MyContext.Provider> </div> ) }
子组件
import React, { useContext } from 'react' import { MyContext } from './parent' export default function Parent() { const data = useContext(MyContext) // 获取父组件提供的context console.log(data) return ( <div> <p>Child</p> </div> ) }
使用步骤
context:export const MyContext = createContext()
provider
和value
提供值:<MyContext.provide value={{name: 'cc', age: 22}} />
context:import { MyContext } from './parent'
const data = useContext(MyContext)
不过在多数情况下我们都不建议使用context
,因为会增加组件的耦合性。
useEffect 在全部渲染完毕后才会执行;useLayoutEffect 会在 浏览器 layout之后,painting之前执行,并且会柱塞DOM;可以使用它来读取 DOM 布局并同步触发重渲染。
export default function LayoutEffect() { const [color, setColor] = useState('red') useLayoutEffect(() => { alert(color) // 会阻塞DOM的渲染 }); useEffect(() => { alert(color) // 不会阻塞 }) return ( <> <div id="myDiv" style={{ background: color }}>颜色</div> <button onClick={() => setColor('red')}>红</button> <button onClick={() => setColor('yellow')}>黄</button> </> ) }
上面的例子中useLayoutEffect会在painting之前执行,useEffect在painting之后执行。
hooks让函数组件拥有了内部状态、生命周期,使用hooks让代码更加的简介,自定义hooks方便了对逻辑的复用,并且摆脱了class组件的this问题;但是在使用hooks时会产生一些闭包问题,需要仔细使用。
【相关推荐:Redis视频教程】
위 내용은 반응 후크와 클래스의 차이점은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!