Sticky Image Loader

11984 단어 React후크
여기까지의 스크롤 Hooks 테크닉으로 스크롤 위치에 따라서 이미지를 읽어들여 해방하는 처리를 구현합니다.
code: github/$ yarn 1210






거동 확인



화면 표시 영역에 들어가고 나서 각 화상은 로드 개시됩니다만, 수중에서 확인하려면 곧바로 리스폰스가 돌아오기 때문에, 별로 효과를 모릅니다. Chrome에서 느린 환경 디버깅을 사용하도록 설정한 다음 확인하면 이해하기 쉽습니다.



memoize 과 render props



Hooks API는 루프나 조건 분기에서는 사용할 수 없는 묶음이 있습니다. 이때 친숙한 render props가 도움이 됩니다.

components/items.tsx
const View = (props: Props) => (
  <div className={props.className}>
    {Assets.map((asset, index) => (
      <Item
        key={index}
        imgPath={asset.imgPath}
        render={({
          imgSrc,
          loaded,
          loadCompleted,
          handleLoadCompleted
        }) => (
          <>
            <Photo
              imgSrc={imgSrc}
              loaded={loaded}
              loadCompleted={loadCompleted}
              onTransitionEnd={handleLoadCompleted}
            />
            <Description
              title={asset.title}
              body={asset.body}
            />
          </>
        )}
      />
    ))}
  </div>
)

이것이 루프 처리에 걸리는 Item 컴퍼넌트입니다. Custom Hooks 를 이용해, 얻어진 state 를 memoize. 상태가 변화했을 때에 한해 rerender props 합니다.

components/item/index.tsx
export default (props: Props) => {
  const {
    state,
    handleLoadStart,
    handleDispose,
    handleLoadCompleted
  } = useImageLoader({
    imgPath: props.imgPath
  })
  return useMemo(
    () => (
      <ScrollWrapper
        onEnter={handleLoadStart}
        onLeave={handleDispose}
      >
        {props.render({
          imgSrc: state.img.src,
          loaded: state.loaded,
          loadCompleted: state.loadCompleted,
          handleLoadCompleted
        })}
      </ScrollWrapper>
    ),
    [state]
  )
}

useImageLoader



이미지를 로드 해제하는 Custom Hooks입니다. 책임이 분명하기 때문에 재사용성이 높은 Custom Hooks라고 할 수 있습니다.

components/item/useImageLoader.ts
const useImageLoader = (props: Props) => {
  const [state, update] = useState({
    img: new Image(),
    loaded: false,
    loadCompleted: false
  })
  const handleLoadStart = useCallback(
    () => {
      state.img.onload = () =>
        update(_state => ({ ..._state, loaded: true }))
      state.img.src = props.imgPath
    },
    [state.img]
  )
  const handleDispose = useCallback(() => {
    update(_state => ({
      ..._state,
      img: new Image(),
      loaded: false,
      loadCompleted: false
    }))
  }, [])
  const handleLoadCompleted = useCallback(() => {
    update(_state => ({
      ..._state,
      loadCompleted: true
    }))
  }, [])
  return {
    state,
    handleLoadStart,
    handleDispose,
    handleLoadCompleted
  }
}

마지막으로, 여기에서 얻어진 핸들러를, 스크롤 처리를 실시하는 Hooks Component 에 바인드 합니다. 이 컴포넌트는 요 전날 게시물에서 사용하는 것과 거의 동일합니다. 매번이므로 오늘은 할애합니다.

components/item/index.tsx
<ScrollWrapper
  onEnter={handleLoadStart}
  onLeave={handleDispose}
>
...
</ScrollWrapper>

좋은 웹페이지 즐겨찾기