상태 비 저장 구성 요소의 기능?


90

여기서<canvas> 찾은 이 멋진 애니메이션을 React 재사용 가능한 구성 요소로 변환하려고합니다 . 이 구성 요소에는 캔버스에 대해 하나의 상위 구성 요소가 필요하고 .function Ball()

성능상의 이유로 Balls상태 비 저장 구성 요소로 만드는 것이 더 좋을 것입니다. 상태 비 저장 구성 요소를 만드는 데 익숙하지 않으며 .NET에서 정의 된 this.update()this.draw함수를 어디에서 정의해야하는지 궁금합니다 function Ball().

상태 비 저장 구성 요소에 대한 함수는 구성 요소 내부 또는 외부로 이동합니까? 즉, 다음 중 어느 것이 더 낫습니까?

1:

const Ball = (props) => {
    const update = () => {
        ...
    }

    const draw = () => {
        ...
    }

    return (
       ...
    );
}

2 :

function update() {
     ...
}

function draw() {
     ...
}

const Ball = (props) => {
    return (
       ...
    );
}

각각의 장단점은 무엇이며 그중 하나가 저와 같은 특정 사용 사례에 더 적합합니까?


어떻게 사용되는지 볼 수 있도록 기존 코드를 게시 할 수 있습니까?
Scimonster

@Scimonster 나는 그것을 포함 된 링크에 게시했다. 여기에 링크가 있습니다. codepen.io/awendland/pen/XJExGv
MarksCode

답변:


113

가장 먼저 주목해야 할 점은 상태 비 저장 기능 구성 요소가 메서드를 가질 수 없다는 것입니다. 상태 비 저장 기능 구성 요소 인 경우 호출 update또는 draw렌더링에 의존해서는 안됩니다 Ball.

대부분의 경우 구성 요소 함수 외부에서 함수를 선언하여 한 번만 선언하고 항상 동일한 참조를 재사용하도록해야합니다. 내부에서 함수를 선언하면 구성 요소가 렌더링 될 때마다 함수가 다시 정의됩니다.

예를 들어 구성 요소의 속성에 따라 다르게 작동하는 이벤트 처리기로 할당하기 위해 구성 요소 내부에 함수를 정의해야하는 경우가 있습니다. 그러나 여전히 외부에서 함수를 정의하고 Ball속성과 바인딩하여 코드를 훨씬 더 깔끔하게 만들고 updateor draw함수를 재사용 할 수 있습니다.

// You can use update somewhere else
const update (propX, a, b) => { ... };

const Ball = props => (
  <Something onClick={update.bind(null, props.x)} />
);

hooks를 사용하는 경우을 사용 useCallback하여 종속성 중 하나 ( props.x이 경우)가 변경 될 때만 함수가 재정의되도록 할 수 있습니다 .

const Ball = props => {
  const onClick = useCallback((a, b) => {
    // do something with a, b and props.x
  }, [props.x]);

  return (
    <Something onClick={onClick} />
  );
}

이것은 잘못된 방법입니다 .

const Ball = props => {
  function update(a, b) {
    // props.x is visible here
  }

  return (
    <Something onClick={update} />
  );
}

를 사용할 때 useCallback, 컴포넌트 외부 updateuseCallback후크 자체 에서 함수를 정의하는 것이 무엇보다 디자인 결정이 update됩니다. 예를 들어, 상태 읽기 / 쓰기. 개인적으로 저는 기본적으로 구성 요소 내부에 정의하고 필요할 때만 재사용 할 수 있도록 선택하여 처음부터 과도한 엔지니어링을 방지합니다. 애플리케이션 로직을 재사용하는 것 외에도 더 구체적인 후크를 사용하여 구성 요소를 표현 용으로 남겨 둡니다. 후크를 사용하는 동안 컴포넌트 외부에서 함수를 정의하는 것은 실제로 애플리케이션 로직에 대해 원하는 React에서 분리 등급에 따라 다릅니다.


감사합니다 Marco. 내 경우에 대해 혼란스러워하고있어 일이 관련되어 this.draw내부 기능 Ball. 그것은 사용하는 ctx부모의 일 것입니다 무슨에서 <canvas>도 및이 사용하는 this아이 어떻게 될지에 대한 키워드 Ball구성 요소를. 두 속성 모두에 액세스 할 수 있도록 상태 비 저장 구성 요소를 구현하는 가장 좋은 통합 방법은 무엇입니까?
MarksCode

this상태 비 저장 기능 구성 요소를 사용할 때는 없습니다 .이를 염두에 두십시오. 캔버스 컨텍스트의 경우 모든 단일에 전달해야하는데 Ball전혀 좋지 않습니다.
마르코 Scabbiolo

그래서이 경우에 당신이 말하는 자식 컴포넌트가없는 것이 최선일까요?
MarksCode

1
@MarcoScabbiolo 아니, 그것은 내 경우가 아니며 이미 화살표 기능을 지원하지 않는 유일한 브라우저는 IE이기 때문에 이미 꽤 오랫동안 기본적으로 화살표 기능을 사용하고 있습니다. 실제로 59 이전의 Chrome 에서 특히 화살표 기능보다 더 느리다고 주장하는 한 기사 에서이 댓글을 찾을 수 있었습니다 . 그리고 Firefox에서는 둘 다 동일한 속도로 작동하기 때문에 꽤 오랜 시간이 걸립니다. 나는 그런 경우라고 말하고 싶지만 그래서 선호하는 방법 : 무슨 차이가 없습니다bind
바딤 Kalinin

1
@ MauricioAvendaño는 어느 쪽이든 작동하지만, Something구성 요소가 컨텍스트를 인식 할 때 부모 구성 요소에 prop X가 있음을 아는 것은 나쁜 습관입니다 . 당신이 묻는 질문과 내가 작성한 샘플 코드에 대해서도 똑같은 일이 발생하며, 컨텍스트에 따라 다르며 단순성을 위해 무시됩니다.
Marco Scabbiolo

12

상태 비 저장 기능 구성 요소 내부에 함수를 가질 수 있습니다. 아래는 예입니다.

 const Action = () => {
  function  handlePick(){
     alert("test");
  }
  return (
    <div>
      <input type="button" onClick={handlePick} value="What you want to do ?" />
    </div>
  );
}

그러나 handlePick()구성 요소가 호출 될 때마다 함수 가 정의 되므로 좋은 방법이 아닙니다 .


11
좋은 습관이 아니라면 대체 솔루션은 무엇입니까?
John Samuel

@JohnSamuel 대안은 handlePick이 한 번만 정의되는 결과 handlePick()와 같이 구성 요소의 위 / 외부 를 정의 function handlePick() { ... }; const Action = () => { ... }하는 것입니다. Action구성 요소의 데이터가 필요한 경우 매개 변수로 handlePick함수에 전달해야 합니다.
James Hay

11
이것이 좋은 관행이 아니라면 대답과 함께 좋은 관행을 추가 할 수 있었을까요? 이제 좋은 연습을 다시 검색해야합니다. (
Shamseer Ahammed

2

useCallback기능적 구성 요소에서 아래와 같이 React 후크 를 사용할 수 있습니다 .

const home = (props) => {
    const { small, img } = props
    const [currentInd, setCurrentInd] = useState(0);
    const imgArrayLength = img.length - 1;
    useEffect(() => {
        let id = setInterval(() => {
            if (currentInd < imgArrayLength) {
                setCurrentInd(currentInd => currentInd + 1)
            }
            else {
                setCurrentInd(0)
            }
        }, 5000);
        return () => clearInterval(id);
    }, [currentInd]);
    const onLeftClickHandler = useCallback(
        () => {
            if (currentInd === 0) {

            }
            else {
                setCurrentInd(currentInd => currentInd - 1)
            }
        },
        [currentInd],
    );

    const onRightClickHandler = useCallback(
        () => {
            if (currentInd < imgArrayLength) {
                setCurrentInd(currentInd => currentInd + 1)
            }
            else {

            }
        },
        [currentInd],
    );
    return (
        <Wrapper img={img[currentInd]}>
            <LeftSliderArrow className={currentInd > 0 ? "red" : 'no-red'} onClick={onLeftClickHandler}>
                <img src={Icon_dir + "chevron_left_light.png"}></img>
            </LeftSliderArrow>
            <RightSliderArrow className={currentInd < imgArrayLength ? "red" : 'no-red'} onClick={onRightClickHandler}>
                <img src={Icon_dir + "chevron_right_light.png"}></img>
            </RightSliderArrow>
        </Wrapper>);
}

export default home;

나는 그것의 부모로부터 'img'를 얻고 있는데 그것은 배열입니다.


0

함수에서 props 또는 컴포넌트의 상태를 사용하려면 useCallback을 사용하여 컴포넌트에 정의해야합니다.

function Component(props){
  const onClick=useCallback(()=>{
     // Do some things with props or state
  },[])
}

반면에 props 또는 state in function을 사용하지 않으려면 컴포넌트 외부에서 정의하십시오.

const computeSomethings=()=>{
   // Do some things with params or side effects
}

function Component(props){
  
}

3
함수 구성 요소 내부에서 메서드에 후크를 사용하는 예를 제공 할 수 있습니까? (상태 방법을 설정하지 않음)
jake-ferguson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.