본문 바로가기
coding/react

리코일, Selectors

by 코딩희송 2023. 3. 30.

atoms, selectors를 입력으로 받아들이는 순수 함수다.
상위 atoms, selectors가 업데이트되면 하위의 selector 함수도 다시 실행된다.
컴포넌트들은 selectors를 atoms처럼 구독할 수 있으며 selectors가 변경되면 컴포넌트들도 다시 렌더링된다.

const fontSizeLabelState = selector({
    key: 'fontSizeLabelState',
    get: ({get}) => {
        const fontSize = get(fontSizeState); // atom에 의존성이 생김
        const unit = 'px';
        return `${fontSize}${unit}`;
    },
});

get속성은 계산될 함수다. 전달되는 get 인자를 통해 atoms와 다른 selector에 접근할 수 있다. 다른 atoms나 selectors에 접근하면 자동적으로 종속 관계가 생성되므로, 참조했던 다른 atoms나 selectros가 업데이트되면 이 함수도 다시 실행된다.

fontSizeLabelState에서 selector은 fontSizeState라는 하나의 atom에 의존성을 갖는다.
개념적으로 fontSizeLabelState selector는 fontSizeState를 입력으로 사용하고 형식화된 글꼴 크기 레이블을 출력으로 반환하는 순수 함수처럼 동작한다.

Selectors는 useRecoilValue()를 통해서 읽을 수 있다. useRecoilValue()는 하나의 atom이나 selector를 인자로 받아 대응하는 값을 반환한다. fontSizeLabelState selector는 writable하지 않기때문에 useRecoilState()를 이용하지 않는다.

function FontButton(){
    const [fontSize, setFontSize] = useRecoilState(fontSizeState);
    const fontSizeLabel = useRecoilValue(fontSizeLabelState);

    return (
        <>
            <div>Current font size: ${fontSizeLabel}</div>
            <button onClick={setFontSize(fontSize + 1)} style={{fontSize}}>Click to Enlarge</button>
        </>
    )
}

버튼을 클릭하면 버튼의 글꼴 크기가 증가하는 동시에 현재 글꼴 크기를 반영하도록 글꼴 크기 레이블을 업데이트하는 두가지 작업이 수행된다.

const todoListFilterState = atom({
	key: 'todoListFilterState',
    default: 'Show All'
})

todoListFilterState와 todoListState를 이용해서 필터링 된 리스트를 내보내는 filteredTodoListState selector를 구성해보자.

const filteredTodoListState = selector({
	key: 'filteredTodoListState',
    get: ({get}) => {
    	const filter = get(todoListFilterState);
        const list = get(todoListState);
        
        switch (filter) {
        	case 'Show Completed':
            	return list.filter((item) => item.isComplete);
            case 'Show Uncompleted':
            	return list.filter((item) => !item.isComplete);
			default:
            	return list;
        }
    }
});

filteredTodoListState는 내부적으로 2개의 의존성 todoListFilterState와 todoListState를 추적한다.
그래서 둘 중 하나라도 변경되면 filteredTodoListState는 재실행된다.

컴포넌트 관점에서 보면 selector는 atom을 읽을 때 사용하는 같은 훅을 사용해서 읽을 수 있다. 그러나 특정한 훅은 쓰기 가능 상태 (= useRecoilState())에서만 작동한다는 점을 유의해야 한다. 모든 atom은 쓰기 가능 상태지만 selector는 일부만 쓰기 가능한 상태(get, set 속성을 둘 다 가지고 있는 selector로 간주된다. 

댓글