JavaScript React+Typescript - 서로 의존하는 드롭다운리스트. (Select relationships)
페이지 정보
본문
안녕하세요. 엔지엠소프트웨어입니다. 일반적인 웹 환경에서 아이템 항목이 의존성을 가지는 경우는 그렇게 흔하지는 않습니다만... 은근히 많이 사용되기도 합니다. 전통적인 웹개발 환경에서는 쉽게 처리할 수 있었던 기능도... React와 Typescript를 사용하다보니 구현에 어려움이 많네요. 아무튼, 아래 그림과 같은 사이트를 선택하면, 여기서 선택한 값으로 라인의 항목이 표시됩니다. 에어리어도 동일합니다.
리엑트 훅(Hook)에서 Select 콘트롤의 value 속성을 채워줘야 합니다. 이 때 현재 Select 콘트롤의 위치(Index)를 알아야 합니다. 그래야 처음 사이트의 항목을 표시할 수 있기 때문입니다. 이렇게 Hook를 연결하면서 상하위의 값을 체크해서 Backend의 RESTful을 호출해야 합니다. 선택 항목에 따라 3개의 Select(ComboBox or DripDownList)가 의존성을 가지면서 갱신하려면 아래와 같이 코드를 작성해야 합니다.
const selectsReducer = (state, action) => {
const { type, payload } = action;
switch (type) {
case "update_planet": {
const newCountry = payload.countries.find(
(c) => c.planet === payload.value
).id;
return {
planet: payload.value,
country: newCountry,
city: payload.cities.find((c) => c.country === newCountry).id,
};
}
case "update_country": {
return {
...state,
country: payload.value,
city: payload.cities.find((c) => c.country === payload.value).id,
};
}
case "update_city": {
return {
...state,
city: payload.value,
};
}
default:
return { ...state };
}
};
위 코드는 백엔드에 데이타를 요청하는 내용이 필요하지만, 이 부분은 각자 처리하면 될거 같습니다. 구조적인 부분을 참고하세요. 각각의 Select에서 이벤트 훅을 사용하는 대신에 한곳에서 각각의 Select를 업데이트하도록 하는게 더 유리하고 관리가 쉽습니다. 하지만~ 리얼타임으로 처리하는 경우엔 이 로직을 사용할 수 없습니다. 예를 들어, 콤보박스를 클릭하는 순간 서버로부터 데이타를 받아와야 한다면 이 방식으로는 처리하기가 쉽지 않습니다. 그래서, useEffect에서 변화를 매번 감지하도록 할수도 있습니다.
export const SelectList = ({ record, onSave, planets, countries, cities }) => {
const [selectedPlanet, setSelectedPlanet] = useState(record.planet);
const [selectedCountry, setSelectedCountry] = useState(record.country);
const [selectedCity, setSelectedCity] = useState(record.city);
/** handle filteredValues in state */
const [filteredCountries, setFilteredCountries] = useState([]);
const [filteredCities, setFilteredCities] = useState([]);
/** use useEffect to update values */
useEffect(() => {
const filteredCountries = countries.filter((c) => c.planet === selectedPlanet);
setFilteredCountries(filteredCountries);
setSelectedCountry(filteredCountries[0].id);
}, [selectedPlanet]);
useEffect(() => {
const filteredCities = cities.filter((c) => c.country === selectedCountry);
setFilteredCities(filteredCities);
setSelectedCity(filteredCities[0].id);
}, [selectedCountry]);
return (
<div>
<select value={selectedPlanet}
onChange={(e) => setSelectedPlanet(e.target.value)}>
{planets.map((p) => (
<option key={p.id} value={p.id}>{p.name}</option>
))}
</select>
<select value={selectedCountry}
onChange={(e) => setSelectedCountry(e.target.value)}>
{filteredCountries.map((c) => (
<option key={c.id} value={c.id}>{c.name}</option>
))}
</select>
<select
value={selectedCity}
onChange={(e) => setSelectedCity(e.target.value)}>
{filteredCities.map((c) => (
<option key={c.id} value={c.id}>{c.name}</option>
))}
</select>
<button onClick={() => onSave({planet: selectedPlanet, country: selectedCountry, city: selectedCity })}>Save</button>
</div>
);
};
가장 간단한 방법은 Select 콘트롤의 갯수가 정해져 있고, 항목들도 고정되어 있는 시나리오일겁니다. 하지만, Select 갯수도 동적이고 그 안의 Option들도 동적인데다 랜덤하다면 어쩔 수 없이 각각의 Select에 Hook을 걸어서 로직적으로 바인딩하고 Select의 Value와 Option 목록을 삭제해야 합니다. 코딩의 자유도가 높지 않은 React, Angular와 같은 환경에서느 어려운 개발이 될겁니다.
개발자에게 후원하기
추천, 구독, 홍보 꼭~ 부탁드립니다.
여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~
감사합니다~
- 이전글1부 - React의 Hooks에 대해 알아보자! 23.04.15
- 다음글ant-design(antd)에서 Modal 안에 컨트롤 데이타 초기화하는 방법. 23.04.13
댓글목록
등록된 댓글이 없습니다.