React
Description: React와 관련된 기술, 경험등을 기록하는 카테고리입니다.
현재 노트: KR-010.20
하위 분류:
- KR-010.20 a React공식사이트에서 UI표현하기 중 중요한 내용만 추출
- KR-010.20 b 상호작용성 더하기
- KR-010.20 c State 관리하기
- KR-010.20 d 탈출구
useEffect를 사용하기전 정말 필요한지 생각해봐야 한다.
렌더링 최소화 하기
- 상태, props 설정 필요한 경우에 하기
계획해 보기
- 현재 작성하는 컴포넌트를 추가하거나 제거해도 기존 시스템에 영향을 덜미치는지? 예를들어 해당 컴포넌트를 추가하고 동작시킨 후 제거 해도 기존 시스템에 문제를 안 일으키는지?
테스트 해보기
- 입력을 빠르게 해보기
- 버튼을 누른 후 대기시간이 있는경우 이 때 입력된 값을 변경해보기
- 같은 동작 2번 실행해보기
- 인증정보 관려시 비로그인으로 해보기
- 값을 변경하고 저장후 , 입력돼 있는 값 변경후 다시 저장해보기
- 화면 크기 바꿔보기
- 비동기 함수가 2개 이상이 같은 상태를 업데이트하는 경우 실행 순서를 바꿔서 테스트해보기
시간에 따라 바뀌는 값
은 필히 여러 조건에서 테스트해보기
Hook 변경하기전 분석하기
- 어떤 상태를 변경하는지?
- 어떤 렌더링 단계인지?
- 어떤 props를 변경하려는지?
- 어떤 hook을 기존에 사용하려는지?
- 변경 후 개선되는게 성능인지, 버그를 줄이기 위해서인지
useEffect
cleanup 함수에서 raceCondtion을 방지하는 방법. 초기 ignore false, !ignore로 함수 실행, return ignore true로 unmount시 동작.
컴포넌트파일 이름규칙 대문자
- Notice that
<MyButton />
starts with a capital letter. That’s how you know it’s a React component. React component names must always start with a capital letter, while HTML tags must be lowercase.
괄호가 없으면 return
뒷 라인에 있는 모든 코드가 무시됩니다!
컴포넌트는 다른 컴포넌트를 렌더링할 수 있지만, 그 정의를 중첩해서는 안 됩니다.
export default와 name export 사용시 고려사항
보편적으로 한 파일에서 하나의 컴포넌트만 export 할 때 default export 방식을 사용하고 여러 컴포넌트를 export 할 경우엔 named export 방식을 사용합니다. 어떤 방식을 사용하든 컴포넌트와 파일의 이름을 의미 있게 명명하는 것은 중요합니다. export default () => {}
처럼 이름 없는 컴포넌트는 나중에 디버깅하기 어렵기 때문에 권장하지 않습니다.
Fragment를 써야하는 이유
JSX는 HTML처럼 보이지만 내부적으로는 일반 JavaScript 객체로 변환됩니다. 하나의 배열로 감싸지 않은 하나의 함수에서는 두 개의 객체를 반환할 수 없습니다. 따라서 또 다른 태그나 Fragment로 감싸지 않으면 두 개의 JSX 태그를 반환할 수 없습니다.
모든 태그는 닫아주기
JSX에서는 태그를 명시적으로 닫아야 합니다. <img>
처럼 자체적으로 닫아주는 태그는 반드시 <img />
형태로 작성해야 하며, <li>oranges
와 같은 래핑 태그도 <li>oranges</li>
형태로 작성해야 합니다.
거의 대부분 캐멀 케이스로!
JavaScript는 변수명에 제한이 있습니다. 예를 들면, 변수명에 대시를 포함하거나 class
처럼 예약어를 사용할 수 없습니다. 이것이 바로 React에서 HTML과 SVG의 어트리뷰트 대부분이 캐멀 케이스로 작성되는 이유입니다. 예를 들면, stroke-width
대신 strokeWidth
로 사용합니다. class
는 예약어이기 때문에, React에서는 DOM의 프로퍼티의 이름을 따서 className
으로 대신 작성합니다.
역사적인 이유로, aria-*
와 data-*
의 어트리뷰트는 HTML에서와 동일하게 대시를 사용하여 작성합니다.
prop의 기본값은 없거나 undefined일 때
이 기본값은 size prop이 없거나 size={undefined}
로 전달될 때 사용됩니다. 그러나 size={null}
또는 size={0}
으로 전달된다면, 기본값은 사용되지 않습니다.
컴포넌트 조건부 렌더링시 삼항 연산자
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
위와 같은 대신에 아래와 같이 작성
return (
<li className="item">
{isPacked ? name + ' ✅' : name}
</li>
);
&&연산자로 조건부 렌더링시 왼쪽에 숫자는 놓으면 안된다
&&
의 왼쪽에 숫자를 두지 마세요.
조건을 테스트하기 위해 JavaScript는 자동으로 왼쪽을 부울로 변환합니다. 그러나 왼쪽이 0
이면 전체 식이 (0
)을 얻게 되고, React는 아무것도 아닌 0
을 렌더링할 것입니다.
화살표 함수의 암시적인 return 반환
화살표 함수는 암시적으로 => 바로 뒤에 식을 반환하기 때문에 return 문이 필요하지 않습니다.
const listItems = chemists.map(person =>
<li>...</li> // 암시적 반환!
);
하지만 => 뒤에 { 가 오는 경우 return 을 명시적으로 반환해야합니다.
const listItems = chemists.map(person => { // 중괄호
return <li>...</li>;
});
key 규칙
- key는 형제 간에 고유해야 합니다. 하지만 같은 key를 다른 배열의 JSX 노드에 동일한 key로 사용해도 괜찮습니다.
- key는 변경되어서는 안 되며 그렇게 되면 key는 목적에 어긋납니다! 렌더링 중에는 key를 생성하지 마세요.
Key가 필요한 이유
React에 key가 필요한 이유는 무엇인가요?
데스크탑의 파일에 이름이 없다고 상상해 보세요. 대신 첫 번째 파일, 두 번째 파일 등 순서대로 파일을 참조할 것입니다. 익숙해질 수도 있지만, 파일을 삭제한다면 혼란스러워질 수도 있습니다. 두 번째 파일이 첫 번째 파일이 되고 세 번째 파일이 두 번째 파일이 되는 식으로 말이죠.
React 렌터 트리에 HTML 태그가 없는 이유
이러한 플랫폼 UI 기본 요소는 React의 일부가 아닙니다. React 렌더 트리는 앱이 렌더링되는 플랫폼에 관계없이 React 앱에 대한 통찰력을 제공할 수 있습니다.
HTML의 class
대신 React에서는 className
- In React, you specify a CSS class with
className
. It works the same way as the HTMLclass
attribute
JSX에서 중괄호를 통한 변수의 리터럴 방식 가능
- JSX lets you put markup into JavaScript. Curly braces let you “escape back” into JavaScript so that you can embed some variable from your code and display it to the user.
Notice how onClick={handleClick}
has no parentheses at the end! Do not call the event handler function: you only need to pass it down. React will call your event handler when the user clicks the button.
useState 문법
You’ll get two things from useState
: the current state (count
), and the function that lets you update it (setCount
). You can give them any names, but the convention is to write [something, setSomething]
.
훅 사용 조건
Hooks are more restrictive than other functions. You can only call Hooks at the top of your components (or other Hooks). If you want to use useState
in a condition or a loop, extract a new component and put it there.
pass down으로 내려주는 함수, 프로퍼티를 props라고한다
The information you pass down like this is called props.
index.js의 필수 항목들
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './styles.css';
import App from './App';
- React
- React’s library to talk to web browsers (React DOM)
- the styles for your components
- the component you created in
App.js
.
React DevTools 사용해보기
- 리액트로 이루어진 페이지의 컴포넌트값을 쉽게 확인하는 툴
- 크롬 확장프로그램으로 다운로드
일반적으로 컴포넌트 리팩토링시 상위 컴포넌트로 상태를 끌어올린다
Lifting state into a parent component is common when React components are refactored.
JavaScript supports closures which means an inner function (e.g. handleClick
) has access to variables and functions defined in an outer function (e.g. Board
). The handleClick
function can read the squares
state and call the setSquares
method because they are both defined inside of the Board
function.
export default function Board() {
const [squares, setSquares] = useState(Array(9).fill(null));
function handleClick() {
const nextSquares = squares.slice();
nextSquares[0] = "X";
setSquares(nextSquares);
}
return (
// ...
)
prps를 미리 호출시 재 렌더링되며 infinite loop 문제 발생
<Square value={squares[0]} onSquareClick={handleClick(0)} />
중요한 것은 해당 함수가 call
이 되는 것이고, 이에 따라 재렌더링됨.
해결방법은 화살표함수 형태로 변경. 즉 클릭이 될 때에만 call
하게 변경
<Square value={squares[0]} onSquareClick={() => handleClick(0)} />
event handling 네이밍 규칭
The DOM <button>
element’s onClick
attribute has a special meaning to React because it is a built-in component. For custom components like Square, the naming is up to you. You could give any name to the Square
’s onSquareClick
prop or Board
’s handleClick
function, and the code would work the same. In React, it’s conventional to use onSomething
names for props which represent events and handleSomething
for the function definitions which handle those events.
props 전달시 onSomething
이벤트를 처리하는 함수 정의에 사용 handleSomething
불변성(immutablility)이 중요한 이유
뒤로가기와 같은 현재데이터를 취소하고 돌리는 일반적인 앱의 기능을 가능하게함
Immutability makes complex features much easier to implement. Later in this tutorial, you will implement a “time travel” feature that lets you review the game’s history and “jump back” to past moves. This functionality isn’t specific to games—an ability to undo and redo certain actions is a common requirement for apps. Avoiding direct data mutation lets you keep previous versions of the data intact, and reuse them later.
재 렌더링이의 코스트를 줄여줌
There is also another benefit of immutability. By default, all child components re-render automatically when the state of a parent component changes. This includes even the child components that weren’t affected by the change. Although re-rendering is not by itself noticeable to the user (you shouldn’t actively try to avoid it!), you might want to skip re-rendering a part of the tree that clearly wasn’t affected by it for performance reasons. Immutability makes it very cheap for components to compare whether their data has changed or not. You can learn more about how React chooses when to re-render a component in the memo
API reference.
React에서의 Key값으로 렌더링, 재렌더링, 삭제 업데이트
Keys tell React about the identity of each component, which allows React to maintain state between re-renders. If a component’s key changes, the component will be destroyed and re-created with a new state.
동적 아이템을 만들 때 적절한 키의 중요성 강조
It’s strongly recommended that you assign proper keys whenever you build dynamic lists. If you don’t have an appropriate key, you may want to consider restructuring your data so that you do.
state의 조건 3가지
- Does it remain unchanged over time? If so, it isn’t state.
- Is it passed in from a parent via props? If so, it isn’t state.
- Can you compute it based on existing state or props in your component? If so, it definitely isn’t state!
library 없이 자식 컴포넌트가 부모 컴포넌트 state 업데이트 하기
양방향 데이터흐름 자식에서 부모로 전달하기
You want to make it so whenever the user changes the form inputs, the state updates to reflect those changes. The state is owned by FilterableProductTable
, so only it can call setFilterText
and setInStockOnly
. To let SearchBar
update the FilterableProductTable
’s state, you need to pass these functions down to SearchBar
:
부모 컴포넌트의 state를 업데이트 하는 함수를 props로 전달하고, 자식 컴포넌트에서는 onChange
와 같은 이벤트 발생으로 해당 state를 업데이트함으로서 재렌더링 하게함