어떻게 갈고리를 사용하여 90퍼센트 더 깨끗한 코드를 작성합니까🎣
React는 기능 프로그래밍 모델에 더 많은 투자를 하고 더 튼튼하고 확장 가능한 UI를 구축하는 위대한 도구를 찾는 것 같다.
2018년 10월 ReactConf일에 React는 Hooks라는 API 제안을 발표했는데 이 제안은 전체 지역사회를 휩쓸었다.개발자들은 그것들을 탐색하고 사용해서 실험을 하기 시작했고 RFC(의견 구하기)에서 대량의 피드백을 받았다.React 16.80은 연결을 지원하는 첫 번째 버전입니다.🎉.
이 글은 내가 해석하려고 시도한 것이다.
1. 코드 논리 재사용
코드 논리를 다시 사용하는 것은 매우 어렵고 상당히 많은 경험이 있어야만 이해할 수 있다는 것을 모두가 알고 있다.약 2년 전, 내가 React를 배우기 시작했을 때, 나는 항상 나의 모든 논리를 봉인하기 위해 클래스 구성 요소를 만들었다.서로 다른 구성 요소 간에 논리를 공유하는 것과 관련이 있을 때, 나는 외관이 비슷한 구성 요소를 만들면 서로 다른 UI를 나타낼 수 있다.하지만 그건 좋지 않아요.나는 DRY원칙을 위반했고 이상적인 상황에서 논리를 중용하지 않았다.
옛길
천천히, 나는 HOC 모드를 이해했다. 이것은 내가 함수식 프로그래밍을 사용하여 코드 논리를 다시 사용할 수 있도록 허용한다.HOC는 단지 간단한 higher order function으로 다른 구성 요소 (Dumb) 를 받아들여 새로운 강화 구성 요소로 되돌아옵니다.이 강화된 구성 요소는 논리를 봉인할 것입니다.
A higher order function is a function that takes a function as an argument, or returns a function.
export default function HOC(WrappedComponent){
return class EnhancedComponent extends Component {
/*
Encapsulate your logic here...
*/
// render the UI using Wrapped Component
render(){
return <WrappedComponent {...this.props} {...this.state} />
}
}
// You have to statically create your
// new Enchanced component before using it
const EnhancedComponent = HOC(someDumbComponent);
// And then use it as Normal component
<EnhancedComponent />
그리고 우리는 함수를 도구로 전달하는 추세에 들어섰다. 이것은 render props 모델의 흥행을 상징한다.렌더링 도구는 기능이 강한 모드입니다. 렌더링 컨트롤러가 바로 당신의 손에 있습니다.이것은 inversion of control(IoC) 설계 원칙을 실현하는 데 도움이 된다.React 문서는 속성을 사용하여 어셈블리 간에 코드를 공유하는 기술로 설명합니다.A component with a render prop takes a function that returns a
React element and calls it instead of implementing its own render logic.
쉽게 말하면, 논리(부작용)를 봉인하기 위해 클래스 구성 요소를 만듭니다. 이 구성 요소는 UI 구현에 필요한 데이터를 전달해서 함수를 호출합니다.
export default class RenderProps extends Component {
/*
Encapsulate your logic here...
*/
render(){
// call the functional props by passing the data required to render UI
return this.props.render(this.state);
}
}
// Use it to draw whatever UI you want. Control is in your hand (IoC)
<RenderProps render={data => <SomeUI {...data} /> } />
비록 이 두 가지 모델 모두 코드 논리를 다시 사용하는 문제를 해결했지만, 그들은 우리에게 포장기 지옥 문제를 남겼다. 아래와 같다.따라서 요약하면 재사용 코드 논리와 관련된 몇 가지 문제점을 볼 수 있다.
2. 대형 구성 요소
구성 요소는 React에서 코드를 다시 사용하는 기본 단원입니다.우리가 하나의 이상의 행위를 우리의 클래스 구성 요소에 추상화해야 할 때, 그것은 왕왕 점점 커지고 유지하기 어려워진다.
A class should have one and only one reason to change,
meaning that a class should have only one job.
다음 코드 예제를 살펴보면 다음과 같은 결론을 얻을 수 있습니다.
export default class GiantComponent extends Component {
componentDidMount(){
//side effects
this.makeRequest();
document.addEventListener('...');
this.timerId = startTimer();
// more ...
}
componentdidUpdate(prevProps){
// extra logic here
}
componentWillUnmount(){
// clear all the side effects
clearInterval(this.timerId);
document.removeEventListener('...');
this.cancelRequest();
}
render(){ return <UI />; }
3. 수업은 사람과 기계에 있어서 모두 어렵다
문제의 성격 측면에서 볼 때, 우리는 서브어셈블리의 함수를 호출하려고 할 때 오류가 발생했다.
TypeError: Cannot read property 'setState' of undefined
그리고 머리를 긁어서 원인을 찾아내려고 했다. 구조 함수에 그것을 연결하는 것을 잊어버렸다.그래서 경험이 있는 개발자들 사이에서도 곤혹스러운 화제다.this gets the value of object who invokes the function
또한 첫 번째 부작용을 수행하기 위해 많은 샘플 코드를 작성해야 합니다.
extends -> state -> componentDidMount -> componentWillUnmount -> render -> return
기계에 대해서도 과정이 어렵다. 이유는 다음과 같다.새로운 API가 등장함에 따라 우리는 논리를 구성 요소 밖으로 완전히 추상화함으로써 이 문제를 해결할 수 있다.간단히 말해서, 유상태 논리를 기능 구성 요소에 연결할 수 있습니다.
React Hooks allow you to use state and other React features without writing a class.
다음 코드 예제를 살펴보겠습니다.
import React, { useState } from 'react';
export default function MouseTracker() {
// useState accepts initial state and you can use multiple useState call
const [mouseX, setMouseX] = useState(25);
const [mouseY, setMouseY] = useState(25);
return (
<div>
mouseX: {mouseX}, mouseY: {mouseY}
</div>
);
}
useState 갈고리에 대한 호출은 현재 상태와 함수를 업데이트합니다.우리의 예에서 현재 상태 값은mouseX이고 setter 함수는setMouseX입니다.매개 변수를useState에 전달하면, 이 매개 변수는 구성 요소의 초기 상태가 됩니다.지금 문제는 setMouseX를 어디라고 부르느냐는 것이다.useState 갈고리 아래에서 호출하면 오류가 발생합니다.이것은 이것을 부르는 것과 같다.setState 클래스 구성 요소의 내부 렌더링 함수입니다.
그래서 답은React가 useEffect이라는 자리 차지 갈고리를 제공해 모든 부작용을 수행하는 데 사용했다는 것이다.
import React, { useState } from 'react';
export default function MouseTracker() {
// useState accepts initial state and you can use multiple useState call
const [mouseX, setMouseX] = useState(25);
const [mouseY, setMouseY] = useState(25);
function handler(event) {
const { clientX, clientY } = event;
setMouseX(clientX);
setMouseY(clientY);
}
useEffect(() => {
// side effect
window.addEventListener('mousemove', handler);
// Every effect may return a function that cleans up after it
return () => window.removeEventListener('mousemove', handler);
}, []);
return (
<div>
mouseX: {mouseX}, mouseY: {mouseY}
</div>
);
}
이 효과는 처음 렌더링되고 업데이트될 때마다 호출됩니다.선택할 수 있는 함수를 되돌려줍니다. 이 함수는 정리 메커니즘이 됩니다.이것은 구독을 추가하고 삭제하는 논리와 밀접하게 연결할 수 있도록 한다.useEffect 호출의 두 번째 인자는 선택할 수 있는 그룹입니다.배열의 요소 값이 변경될 때만 효과가 다시 실행됩니다.이것을 shouldComponentUpdate의 작업 원리로 상상해 보세요.효과를 실행하고 한 번만 정리하려면 빈 그룹 ([]) 을 두 번째 인자로 전달할 수 있습니다.이것은 React에 당신의 효과가 도구나 상태의 어떤 값에 의존하지 않기 때문에 영원히 다시 실행할 필요가 없다는 것을 알려 줍니다.익숙한 component Did Mount와 component Will Unmount의 심지 모형과 매우 가깝다.만약 네가 use Effect hook에 대해 깊이 이해하고 싶다면, 나는 이미 다른 문장을 썼다.
그러나 우리의 쥐덫 부품은 여전히 논리를 포함하고 있지 않습니까?다른 구성 요소도 마우스 모브 행동을 공유하고 싶다면요?그 밖에 효과 (예를 들어 창 크기 조정) 를 추가하면 관리가 좀 어려워지고, 클래스 구성 요소에서 본 것과 같은 문제로 돌아갑니다.
이제 진정한 마법은 함수 구성 요소 밖에서 사용자 정의 갈고리를 만들 수 있는 것이다.이것은 논리를 하나의 단독 모듈로 추상화하고 서로 다른 구성 요소 사이에서 공유하는 것과 유사하다.행동 좀 봅시다.
// you can write your custom hooks in this file
import { useState, useEffect } from 'react';
export function useMouseLocation() {
const [mouseX, setMouseX] = useState(25);
const [mouseY, setMouseY] = useState(25);
function handler(event) {
const { clientX, clientY } = event;
setMouseX(clientX);
setMouseY(clientY);
}
useEffect(() => {
window.addEventListener('mousemove', handler);
return () => window.removeEventListener('mousemove', handler);
}, []);
return [mouseX, mouseY];
}
이제 다음과 같이 쥐덫 구성 요소 코드(90%)를 업데이트된 버전으로 정리할 수 있습니다.import React from 'react';
import { useMouseLocation } from 'customHooks.js';
export default function MouseTracker() {
// using our custom hook
const [mouseX, mouseY] = useMouseLocation();
return (
<div>
mouseX: {mouseX}, mouseY: {mouseY}
</div>
);
}
이것은 말로 표현할 수 없을 정도로 절묘한 순간이다.아닌가?그러나 그들을 안정시키고 칭찬하기 전에 우리가 어떤 규칙에 주의해야 하는지 살펴보자.
갈고리 규칙
이 규칙들을 해석하는 것은 본문의 범위를 넘어섰다.궁금하시면 루디 아델리의 docs과 article을 읽어 보세요.
React는 이 두 규칙을 실행하는 데 사용되는 eslint-plugin-react-hooks이라는 ESLint 플러그인도 발표했다.다음 명령을 실행하여 프로젝트에 추가할 수 있습니다.
# npm
npm install eslint-plugin-react-hooks --save-dev
# yarn
yarn add eslint-plugin-react-hooks --dev
이 글은 내가 2018년 12월 시드니 회의에서 한 강연의 일부분이다.나는 이 문장이 너의 흥미를 불러일으켜 네가 한번 시도해 볼 수 있기를 바란다.나는 React roadmap에 대해 매우 흥분했다. 그것은 매우 전도가 유망해 보이고, 우리가 현재 React를 사용하는 방식을 바꿀 수도 있다.너는 link에서 원본 코드와 시범을 찾을 수 있다.
하면, 만약, 만약...❤️ 꼭 웃게 해줄게.😀. 더 많아요.
Reference
이 문제에 관하여(어떻게 갈고리를 사용하여 90퍼센트 더 깨끗한 코드를 작성합니까🎣), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/aman_singh/how-to-write-90-cleaner-code-with-hooks-1mmj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)