적은 것이 더 많습니다. React 코드를 단순화하여 애플리케이션 성능 향상 - 2부
23864 단어 reacttutorialwebdevjavascript
React 구성 요소 단순화
기존 구성 요소를 대폭 분해하지 않고 구성 요소를 단순화하기 위해 취할 수 있는 여러 전략이 있습니다. 각 전략은 다른 블로그에서 다룹니다.
useEffect
및 useState
redux
및 redux-saga
가 실제로 필요한지 확인서비스 및 사용자 지정 후크로 처리 연기
React는 특히 주입 가능한 리소스를 통해 프레임워크에 구워진 Angular와 달리 서비스 개념이 부족합니다. React 개발자로서 우리는 이 기능을 프로젝트에 적용해야 합니다. 서비스는 특정 기능을 깔끔하게 캡슐화하고 TypeScript 캐스팅을 통해 교환 가능한 리소스가 되며 프레젠테이션 계층에서 논리를 이동하는 또 다른 단계입니다.
종종 동일한 구성 요소에서 가져오기 및 표시를 수행할 수 있는 구성 요소를 볼 수 있습니다.
const myComponent: React.FC = () => {
const [ todos, setTodos ] = useState<any>([]);
useEffect(async () => {
const result = await axios.get("https://jsonplaceholder.typicode.com/todos");
const todos = res.data.filter(!!todos.completed));
setTodos(todos);
});
return (
<ul>
{ todos.map(item => (
<li key={item.id}>
<a href={`https://jsonplaceholder.typicode.com/todos/${item.id}`>{item.title}</a>
</li>
))}
</ul>
)
}
이 구성 요소에는 그다지 문제가 없어 보이는 표면 수준입니다. 그러나 API, 추가 유효성 검사 및 데이터 조작의 오류 처리를 시작해야 하는 경우에는 어떻게 해야 합니까? 우리의
useEffect
후크는 갑자기 과부하가 걸리고 서비스로 연기될 수 있고 해야 하는 동작으로 부풀려집니다.useEffect(async () => {
try {
const result = await axios.get("https://jsonplaceholder.typicode.com/todos");
const todos = res.data.filter(!!todos.completed));
setTodos(todos);
} catch (e) {
setLoaded(false);
setErrorMessage("Could not load todos, please refresh your browser and make sure you're connected to the internet!");
}
});
useEffect
후크에 더 많이 추가할수록 구성 요소가 더 복잡해지고 테스트하기가 더 어려워집니다. 지연/비동기 렌더링은 이미 jest 및 효소 처리 업데이트와 같은 도구를 사용하여 테스트를 어렵게 만들고 있지만 쉽지는 않습니다.API 처리를 서비스로 이동하여 일관되게 요청하고 오류를 처리하고
useEffect
코드를 사용자 지정 후크로 분리하여 이 코드를 단순화할 수 있습니다.type Todo = { id: number, title: string };
type TodosService = {
todos: async (completed?: boolean) => Promise<Array<Todo>>,
todo: async (id: number) => Promise<Todo>
};
class TodosServiceImpl implements TodosService {
async todos(completed?: boolean): Promise<Array<Todo>> {
try {
const result = await axios.get("https://jsonplaceholder.typicode.com/todos");
if (completed !== undefined) {
return res.data.filter(todo => todo.completed === completed));
}
return res.data;
} catch (e) {
throw "Could not load todos, please refresh your browser and make sure you're connected to the internet!";
}
}
async todo(id: number): Promise<Todo> {
try {
const result = await axios.get(`https://jsonplaceholder.typicode.com/todos/${id}`);
return res.data;
} catch (e) {
throw `Could not load todo ${id}, please refresh your browser and make sure you're connected to the internet!`;
}
}
}
교환 가능한 서비스가 필요한 경우
TodosService
의 계약을 만족하는 한 새로운 서비스를 제공할 수 있습니다.const todosService: TodosService = {
todos: async (completed?: boolean): Promise<Array<Todo>> => {...}
todo: async (id: number): Promise<Todo> => {...}
}
// test of the implementation
이제 서비스 구현이 완료되었으므로 구성 요소에서 사용할 수 있습니다.
const todosService: TodosService = new TodosServiceImpl();
const useTodosLoader = (todosService: TodosService) => {
const [ todos, setTodos ] = useState<Array<Todos>>([]);
const [ hasError, setHasError ] = useState<boolean>(false);
const [ loaded, setLoaded ] = useState<boolean>(false);
useEffect(async () => {
try {
const list = await todosService.todos();
setTodos(list);
setLoaded(true);
} catch (e) {
setHasError(true);
}
}, []);
return { todos, hasError, loaded };
}
const myComponent: React.FC<{ todosService: TodosService }> = ({ todosService }) => {
const { todos, hasError, loaded } = useTodosLoaded(todosService);
return (
<ul>
{ todos.map(item => (
<li key={item.id}>
<a href={`https://jsonplaceholder.typicode.com/todos/${item.id}`>{item.title}</a>
</li>
))}
</ul>
)
}
위 코드의 모든 측면은 테스트 가능합니다. serice가 호출되었는지 확인할 수 있고 API가 호출되었는지도 확인할 수 있습니다.
MyComponent
의 응답을 통해 useTodoLoader
의 로딩을 확인할 수 있으며, 동작을 바로 조롱하고 스텁할 수 있습니다. 구성 요소를 단순화하기 위해 코드 양을 최소한 두 배로 늘렸지만 코드의 증가는 기능 코드와 테스트 코드의 단순성에 정비례합니다.사용자 정의 후크를 사용하면 특히
useState
후크를 사용하여 상태를 조작할 때 동작을 논리적으로 그룹화할 수 있습니다. 후크의 출력을 구성 요소에서 사용하도록 노출하여 후크가 상태를 변경할 때 업데이트되도록 할 수 있습니다. 이것은 특히 useState
를 사용하여 구성 요소 간의 상태를 유지하는 경우 교차 구성 요소를 사용하는 풍부한 기능을 제공합니다.const useMyState = () => {
const [ myState, setMyState ] = useState(true);
return { myState, setMyState }
}
const myComponent = () => {
const { myState } = useMyState();
...
}
const myOtherComponent = () => {
const { myState, setMyState } = useMyState();
useEffect(() => {
setTimeout(() => {setMyState(false)});
}, []);
...
}
후크를 사용하여 이벤트 스트림을 구독할 수도 있습니다. 이를 통해 연결되지 않은 여러 구성 요소가 상태 변경을 기반으로 하거나 이벤트에 의해 구동되는 동시에 업데이트할 수 있습니다.
const myEventStream = () => {
const [ myState, setMyState ] = useState(null);
useEffect(() => {
const subscription = observable.subscribe();
subscription.next(event => setMyState(event.data));
return () => subscription.unsubscribe();
})
}
const myComponent = () => {
const { myState } = useMyState();
...
}
const myOtherComponent = () => {
const { myState } = useMyState();
...
}
observable.next({data: { foo: "bar"}});
// Updates myComponent
// Updates myOtherComponent
오버로딩 방지
useEffect
및 useState
에 대해 살펴볼 다음 기사를 기대해 주세요.
Reference
이 문제에 관하여(적은 것이 더 많습니다. React 코드를 단순화하여 애플리케이션 성능 향상 - 2부), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/jmitchell38488/less-is-more-simplify-your-react-code-to-super-power-your-applications-part-2-4jam텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)