캐릭터 구동 개발에 대한 추천[전편]
관심 작용의 구성 요소의 실현
서버에서 hoge와fuga를 가져오면 화면에 표시되는 구성 요소를 실행합니다.
당신은 아래의 어떤 구성 요소의 쓰기 방법이 좋다고 생각합니까?
모드 1
const HogeFugaComponent = () => {
const [isLoadingHoge, setIsLoadingHoge] = useState(false);
const [hoge, setHoge] = useState(null);
const [isLoadingFuga, setIsLoadingFuga] = useState(false);
const [fuga, setFuga] = useState(null);
useEffect(() => {
fetchHoge()
.then(hoge => {
setHoge(hoge);
})
})
useEffect(() => {
fetchFuga()
.then(resFuga => {
setFuga(resFuga);
})
})
return <div>{fuga}{hoge}</div>
}
모드 2const HogeFugaComponent = () => {
// hogeを表示する機能
const [isLoadingHoge, setIsLoadingHoge] = useState(false);
const [hoge, setHoge] = useState(null);
useEffect(() => {
fetchHoge()
.then(hoge => {
setHoge(hoge);
})
})
// fugaを表示する機能
const [isLoadingFuga, setIsLoadingFuga] = useState(false);
const [fuga, setFuga] = useState(null);
useEffect(() => {
fetchFuga()
.then(resFuga => {
setFuga(resFuga);
})
})
// 表示
return <div>{fuga}{hoge}</div>
}
리액트에 익숙하지 않은 사람에게 useState
리액트의 상태 관리 함수라고 설명한다.되돌아오는 값은 그룹입니다. 첫 번째는 실제 상태이고, 두 번째는setter입니다.또한useEffect
리액트 구성 요소에서 서버와 통신하는 등 부작용을 일으키는 코드를 쓰는 곳이다.useEffect
구성 요소가 마운트된 후에 실행됩니다.추천 모드 2.왜냐? 패턴2처럼 관련 물건을 부근에 집중하는 것이 모듈화되기 쉽기 때문이다.React의 모듈화는 모듈화와 사용자 정의 연결 등을 통해 실현할 수 있다.
const HogeFugaComponent = () => {
// hogeを表示する機能
const [hoge, isLoadingHoge] = useHoge(); // カスタムフック。実装は省略
// fugaを表示する機能
const [fuga, isLoadingFuga] = useFuga(); // カスタムフック。実装は省略
// 表示
return <div>{fuga}{hoge}</div>
}]
모드 2처럼 쓰려고.
모드 1과 모드 2는 모두 비슷한 기능을 수집했다.모드 1은 React에서 제공하는 어셈블리의 기능 단위로 정리됩니다.모드 2에서 구성 요소가 제공하고자 하는 기능 단위로 정리되었습니다.
모드 2를 어떻게 쓰지?그것은 구성 요소를 명확하게 쓰는 작용을 통해 실현될 수 있다.아래와 같이 doc의 역할을 조로 나누어 쓴 다음에 코드에 주석으로 분할하여 표시한다.
/**
* 役割:
* - hogeを表示する機能
* - fugaを表示する機能
*/
const HogeFugaComponent = () => {
/* ------------------------ */
/* hogeを表示する機能 */
/* ------------------------ */
const [hoge, isLoadingHoge] = useHoge();
/* ------------------------ */
/* fugaを表示する機能 */
/* ------------------------ */
const [fuga, isLoadingFuga] = useFuga();
// 表示
return <div>{fuga}{hoge}</div>
}
일부러 이렇게 쓴 사람은 없지.캐릭터를 코드에 주석으로 명시한 장점이다./**
* 役割:
* - 状態保持機能
* - 副作用機能
*/
const HogeFugaComponent = () => {
/* ------------------------ */
/* 状態保持機能 */
/* ------------------------ */
const [isLoadingHoge, setIsLoadingHoge] = useState(false);
const [hoge, setHoge] = useState(null);
const [isLoadingFuga, setIsLoadingFuga] = useState(false);
const [fuga, setFuga] = useState(null);
/* ------------------------ */
/* 副作用機能 */
/* ------------------------ */
useEffect(() => {
fetchHoge()
.then(hoge => {
setHoge(hoge);
})
})
useEffect(() => {
fetchFuga()
.then(resFuga => {
setFuga(resFuga);
})
})
// 表示
return <div>{fuga}{hoge}</div>
}
실례
/**
* 役割:
* - チャンネルを検索できる。
* - チャンネル一覧を表示する。 -> ChannelListへ委譲
* - チャンネルを選択すると、チャット画面に移動する。 -> ChannelListへ委譲
*/
export const ChannelIndex: React.FC = () => {
/* ------------------------ */
/* 共通 */
/* ------------------------ */
const history = useHistory();
const location = useLocation();
const params = queryString.parse(
location.search,
) as Partial<ChannelIndexPageQuery>;
/* ------------------------ */
/* チャンネル一覧表示 */
/* ------------------------ */
const [isLoading, setIsLoading] = useState(false);
const [channels, setChannels] = useState<Channel[]>([]);
const [total, setTotal] = useState(0);
// URLが変更されると(つまり検索条件が変更すると)、ページの最初までスクロール
useEffect(() => {
window.scrollTo(0, 0);
}, [location]);
/* ------------------------ */
/* チャンネル検索 */
/* ------------------------ */
// NOTE: 検索は基本的に
// 1.urlにpush
// 2.urlの変更を検知してurlからparamsを取得しfetch
// という流れで行われる。
// この方針をとった理由としては、検索条件を内部stateではなくurlに保持することによって、リンクでの共有が可能になるから。
const PAGE_UNIT = 20;
const currentPage = Number.parseInt(params.currentPage || '1', 10);
const handleSearchPage = (page: number) => {
history.push({
search: queryString.stringify({
...params,
currentPage: page.toString(),
}),
});
};
const handleSearchSubmit = (text: string) => {
history.push({
search: queryString.stringify({
...params,
keyword: text,
}),
});
};
useEffect(() => {
const offset = (currentPage - 1) * PAGE_UNIT;
const limit = PAGE_UNIT;
setIsLoading(true);
ChannelRequest.search({
keyword: params.keyword,
offset: offset.toString(),
limit: limit.toString(),
})
.then((res) => {
if (!res.isSuccess) {
notify('error', res.error);
return;
}
setTotal(res.header.total);
setChannels(res.body);
})
.finally(() => {
setIsLoading(false);
});
}, [
// NOTE: paramsで指定するとループするため、明示的に依存プロパティを指定する。
currentPage,
params.keyword,
params.limit,
params.offset,
]);
return (
<div className={classes.Cover}>
<Container className={classes.Container}>
<Search className="mb-3 h-2" onSubmit={handleSearchSubmit} />
<ChannelList
channels={channels}
isLoading={isLoading}
currentPage={currentPage}
pageUnit={PAGE_UNIT}
total={total}
handlePage={handleSearchPage}
searchKeyword={params.keyword || ''}
/>
</Container>
</div>
);
};
시험에서도 대응하는 역할을 점검하면 된다고 생각합니다.describe('<ChannelIndex />', () => {
describe('チャンネルを検索できる。', () => {
test.todo('チャンネルをキーワードで検索できる');
test.todo('次のページのチャンネルを検索できる');
test.todo('前のページのチャンネルを検索できる');
});
});
끝맺다
아래의 일을 고려할 때, 나는 이 작법을 반짝였다.
결과는 TDD의 의도 프로그래밍과 동일합니다.
Reference
이 문제에 관하여(캐릭터 구동 개발에 대한 추천[전편]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/dove/articles/dd42b2f46fc0f3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)