기본적으로 props와 state는 컴포넌트가 무엇을 어떻게 렌더링하는지 알 수있는 두 가지 방법입니다. 응용 프로그램 상태의 어느 부분이 상태에 속하고 일부 최상위 저장소에 해당하는지는 React의 작동 방식보다 앱 디자인과 더 관련이 있습니다. 가장 간단한 결정 방법 인 IMO는이 특정 데이터가 전체 응용 프로그램에 유용한 지 아니면 로컬 정보인지 여부를 생각하는 것입니다. 또한 상태를 복제하지 않는 것이 중요하므로 소품에서 일부 데이터를 계산할 수 있으면 소품에서 계산해야합니다.
예를 들어, a) 목록에서 일부 값을 선택하고 b) 열거 나 닫을 수있는 (예 : 옵션 목록이 표시되거나 숨겨 질 수있는) 드롭 다운 컨트롤 (사용자 지정 스타일 지정을 위해 표준 HTML 선택을 래핑)이 있다고 가정 해 보겠습니다. 이제 앱에 일종의 항목 목록이 표시되고 드롭 다운 컨트롤이 목록 항목을 필터링한다고 가정 해 보겠습니다. 그런 다음 활성 필터 값을 소품으로 전달하고 개 / 폐 상태를 로컬로 유지하는 것이 가장 좋습니다. 또한 기능을 수행하려면 드롭 다운 요소 내부에서 호출되는 상위 구성 요소에서 onChange 핸들러를 전달하고 업데이트 된 정보 (선택한 새 필터)를 즉시 저장소로 보냅니다. 반면에 사용자가 실제로 값을 변경할 때까지 나머지 응용 프로그램은 컨트롤이 열려 있는지 실제로 신경 쓰지 않기 때문에 열린 / 닫힘 상태를 드롭 다운 구성 요소 내부에 유지할 수 있습니다.
다음 코드는 완전히 작동하지 않으므로 CSS와 드롭 다운 클릭 / 블러 / 변경 이벤트 처리가 필요하지만 예제를 최소화하고 싶었습니다. 차이를 이해하는 데 도움이되기를 바랍니다.
const _store = {
items: [
{ id: 1, label: 'One' },
{ id: 2, label: 'Two' },
{ id: 3, label: 'Three', new: true },
{ id: 4, label: 'Four', new: true },
{ id: 5, label: 'Five', important: true },
{ id: 6, label: 'Six' },
{ id: 7, label: 'Seven', important: true },
],
activeFilter: 'important',
possibleFilters: [
{ key: 'all', label: 'All' },
{ key: 'new', label: 'New' },
{ key: 'important', label: 'Important' }
]
}
function getFilteredItems(items, filter) {
switch (filter) {
case 'all':
return items;
case 'new':
return items.filter(function(item) { return Boolean(item.new); });
case 'important':
return items.filter(function(item) { return Boolean(item.important); });
default:
return items;
}
}
const App = React.createClass({
render: function() {
return (
<div>
My list:
<ItemList items={this.props.listItems} />
<div>
<Dropdown
onFilterChange={function(e) {
_store.activeFilter = e.currentTarget.value;
console.log(_store); // in real life, some action would be dispatched here
}}
filterOptions={this.props.filterOptions}
value={this.props.activeFilter}
/>
</div>
</div>
);
}
});
const ItemList = React.createClass({
render: function() {
return (
<div>
{this.props.items.map(function(item) {
return <div key={item.id}>{item.id}: {item.label}</div>;
})}
</div>
);
}
});
const Dropdown = React.createClass({
getInitialState: function() {
return {
isOpen: false
};
},
render: function() {
return (
<div>
<select
className="hidden-select"
onChange={this.props.onFilterChange}
value={this.props.value}>
{this.props.filterOptions.map(function(option) {
return <option value={option.key} key={option.key}>{option.label}</option>
})}
</select>
<div className={'custom-select' + (this.state.isOpen ? ' open' : '')} onClick={this.onClick}>
<div className="selected-value">{this.props.activeFilter}</div>
{this.props.filterOptions.map(function(option) {
return <div data-value={option.key} key={option.key}>{option.label}</div>
})}
</div>
</div>
);
},
onClick: function(e) {
this.setState({
isOpen: !this.state.isOpen
});
}
});
ReactDOM.render(
<App
listItems={getFilteredItems(_store.items, _store.activeFilter)}
filterOptions={_store.possibleFilters}
activeFilter={_store.activeFilter}
/>,
document.getElementById('root')
);