react useEffect 폐쇄 된 구덩이

문제 코드
useEffect 로 인 한 폐쇄 문제 코드 보기

const btn = useRef();
const [v, setV] = useState('');

useEffect(() => {
    let clickHandle = () => {
        console.log('v:', v);
    }
    btn.current.addEventListener('click', clickHandle)
    
    return () => {
        btn.removeEventListener('click', clickHandle)
    }
}, []);
    
const inputHandle = e => {
    setV(e.target.value)
}

return (
        <>
            <input value={v} onChange={inputHandle} />
            <button ref={btn} >  </button>
        </>
    )

useEffect 의 의존 항목 배열 이 비어 있 기 때문에 페이지 렌 더 링 이 완 료 된 후에 내부 코드 는 한 번 만 실행 되 고 페이지 가 소각 되 어 다시 실 행 됩 니 다.이 때 입력 상자 에 임의의 문 자 를 입력 하고 테스트 단 추 를 누 르 면 출력 이 비어 있 습 니 다.그 다음 에 어떤 문 자 를 입력 하고 테스트 단 추 를 누 르 면 출력 결과 가 비어 있 습 니 다.
왜 이러 지?사실은 폐쇄 로 인 한 것 이다.
발생 원인
함수 의 역할 영역 은 함수 가 정 의 될 때 결정 된다.
btn 에 클릭 이 벤트 를 등록 할 때 역할 영역 은 다음 과 같 습 니 다.

접근 할 수 있 는 자유 변수 v 는 아직 비어 있 습 니 다.이벤트 가 실 행 될 때 클릭 반전 함 수 를 실행 합 니 다.이 때 실행 컨 텍스트 를 만 들 고 도 메 인 체인 을 실행 컨 텍스트 에 복사 합 니 다.
  • 입력 상자 에 문 자 를 입력 하지 않 으 면 받 은 v 를 누 르 면 원래 의 v
  • 입력 상자 에 문 자 를 입력 하면 setV 를 호출 하여 state 를 수정 합 니 다.페이지 가 render 를 터치 하면 구성 요소 내부 코드 가 다시 실 행 됩 니 다.v 를 다시 설명 하면 v 는 더 이상 원래 의 v 가 아 닙 니 다.여기 서 이벤트 의 역할 영역 에 있 는 v 인지 오래된 v 인지 클릭 합 니 다.이것 은 서로 다른 v
  • 장면 이 생기다
  • 이벤트 귀속.예 를 들 어 예제 코드 에서 페이지 초기 렌 더 링 이 끝 난 후에 한 번 만 이벤트 에 연결 하 는 경우,예 를 들 어 echarts 를 사용 하여 useEffect 에서 echarts 의 인 스 턴 스 를 가 져 오고 이벤트
  • 타이머.페이지 를 불 러 온 후 타이머 에 등록 하면 타이머 안의 함수 도 이러한 패 킷 문 제 를 일 으 킬 수 있 습 니 다.
  • 해결 방법
    이 폐쇄 문제 에 대하 여 아래 에 대략 5 가지 해결 방법 을 제시 하 다.
    1.할당 방식 으로 v 를 직접 수정 하고 v 를 수정 하 는 방법 을 useCallback 으로 감 싸 줍 니 다.
    v 를 수정 하 는 방법 을 useCallback 으로 감 싸 면 useCallback 패키지 의 함수 가 캐 시 됩 니 다.의존 항목 의 배열 이 비어 있 기 때문에 여기 서 직접 값 을 부여 하 는 방식 으로 v 는 오래된 v 입 니 다.이 방법 은 추천 하지 않 습 니 다.setState 가 공식 적 으로 추천 하 는 state 를 수정 하 는 방식 이기 때문에 setV 를 사용 하 는 것 은 rerender 를 촉발 하기 위해 서 입 니 다.
    
    // v       const    var,      
    var [v, setV] = useState('');
    
    const inputHandle = useCallback(e => {
        let { value } = e.target
        v = value
        setV(value)
    }, [])
    
    
    2.useEffect 의존 항목 에 v 추가
    이것 은 아마 대부분의 사람들 이 먼저 생각 하 는 방법 일 것 이다.v 가 오래된 것 이 라면 v 가 업 데 이 트 될 때마다 사건 을 다시 등록 하면 되 지 않 겠 는가?그러나 이런 것 은 매번 v 업데이트 가 다시 등록 되 어야 하고 이론 은 한 번 만 등록 해 야 하 는 사건 이 여러 번 이 되 어야 한다.
    3.v 가 다시 밝 혀 지지 않도록
    let 또는 var 방식 으로 v 대신 변 수 를 설명 하고 이 변 수 를 직접 수정 합 니 다.setState 관련 함수 가 render 를 촉발 하 는 것 이 아니 라 다시 설명 되 지 않 습 니 다.클릭 한 리 셋 함수 에서'최신'값 을 얻 을 수 있 습 니 다.그러나 이 방법 은 더욱 추천 하지 않 습 니 다.예 를 들 어 input 구성 요 소 는 rerender 가 없 기 때문에 처음부터 끝까지 빈 값 을 표시 합 니 다.조작 예상 에 부합 되 지 않 습 니 다.
    4.useState 대신 useRef 사용
    
    const btn = useRef();
    const vRef = useRef('');
    const [v, setV] = useStat('');
    
    useEffect(() => {
        let clickHandle = () => {
            console.log('v:', vRef.current);
        }
        btn.current.addEventListener('click', clickHandle)
        
        return () => {
            btn.removeEventListener('click', clickHandle)
        }
    }, []);
    
    const inputHandle = e => {
        let { value } = e.target
        vRef.current = value
        setV(value)
    }
    
    return (
            <>
                <input value={v} onChange={inputHandle} />
                <button ref={btn} >  </button>
            </>
        )
    
    
    useRef 의 방안 이 유효한 이 유 는 매번 input 의 change 가 vRef 라 는 대상 의 current 속성 을 수 정 했 기 때 문 입 니 다.vRef 는 항상 그 vRef 입 니 다.rerender 라 도 vRef 가 대상 이기 때문에 변 수 는 스 택 메모리 에 저 장 된 값 은 이 대상 이 메모리 에 저 장 된 주소 입 니 다.하나의 인용 일 뿐 대상 의 특정한 속성 만 수정 합 니 다.이 인용 은 변 하지 않 습 니 다.그래서 이벤트 의 역할 도 메 인 체인 을 클릭 하면 항상 같은 vRef 를 방문 합 니 다.

    5.v 를 대상 유형 으로 변경
    사실 useRef 를 사용 하 는 것 과 마찬가지 로 대상 이 라면 어떤 속성 만 수정 해도 이 state 가 가리 키 는 주 소 를 바 꾸 지 않 습 니 다.
    코드 주소
    여기,이곳테스트 코드 보기
    여기 서 react useEffect 폐쇄 된 구덩이 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 react useEffect 폐쇄 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기