私の会社では、WebアプリケーションのフロントエンドをReactJSに移行しています。 Reduxなしでcreate-react-app(v16に更新)を使用しています。今、私は次の画像によって構造を簡素化できるページにこだわっています:
3つのコンポーネント(SearchableList、SelectableList、およびMap)によって表示されるデータは、MainContainerのcomponentDidMount()
メソッドの同じバックエンドリクエストで取得されます。このリクエストの結果はMainContainerの状態で保存され、ほぼこのような構造になります。
_state.allData = {
left: {
data: [ ... ]
},
right: {
data: [ ... ],
pins: [ ... ]
}
}
_
LeftContainerは、MainContainerからprop _state.allData.left
_を受け取り、_props.left.data
_を再びSearchとしてSearchableListに渡します。
RightContainerは、MainContainerから__state.allData.right
_をpropとして受け取り、_props.right.data
_をSelectableListに、_props.right.pins
_をMapに渡します。
SelectableListはチェックボックスを表示して、そのアイテムに対するアクションを許可します。 SelectableListコンポーネントのアイテムでアクションが発生するたびに、マップピンに副作用が生じる可能性があります。
SelectableListで表示されるアイテムのすべてのIDを保持するリストをRightContainerの状態で保存することにしました。このリストは、SelectableListとMapの両方に小道具として渡されます。次に、SelectableListにコールバックを渡します。選択が行われるたびに、RightContainer内のIDのリストが更新されます。新しいプロップはSelectableListとMapの両方に到着するため、両方のコンポーネントでrender()
が呼び出されます。
これはうまく機能し、SelectableListとMapに発生する可能性のあるすべてをRightContainer内に保持するのに役立ちますが、これがlifting-state-upおよびsingle-source- of-truthコンセプト。
実行可能な代替案として、MainContainerの__selected
_の各項目に_state.right.data
_プロパティを追加し、選択コールバックを3レベルSelectableListに渡し、MainContainerで可能なすべてのアクションを処理することを考えました。ただし、選択イベントが発生するとすぐに、LeftContainerとRightContainerのロードが強制的に行われ、特にLeftContainerで不要なshouldComponentUpdate()
を回避するためにrender()
などのロジックを実装する必要が生じます。
アーキテクチャとパフォーマンスの観点からこのページを最適化する最適なソリューションはどれですか?
以下に、状況を理解するのに役立つ私のコンポーネントの抜粋があります。
MainContainer.js
_class MainContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
allData: {}
};
}
componentDidMount() {
fetch( ... )
.then((res) => {
this.setState({
allData: res
});
});
}
render() {
return (
<div className="main-container">
<LeftContainer left={state.allData.left} />
<RightContainer right={state.allData.right} />
</div>
);
}
}
export default MainContainer;
_
RightContainer.js
_class RightContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedItems: [ ... ]
};
}
onDataSelection(e) {
const itemId = e.target.id;
// ... handle itemId and selectedItems ...
}
render() {
return (
<div className="main-container">
<SelectableList
data={props.right.data}
onDataSelection={e => this.onDataSelection(e)}
selectedItems={this.state.selectedItems}
/>
<Map
pins={props.right.pins}
selectedItems={this.state.selectedItems}
/>
</div>
);
}
}
export default RightContainer;
_
前もって感謝します!
これに関する私の正直なアドバイス。経験から:
Reduxは簡単です。理解とスケーリングは簡単ですが、特定のユースケースではReduxを使用する必要があります。
Reduxはアプリをカプセル化するため、次のようなものを保存することを考えることができます。
世界規模で必要なもの。 react-reduxでは、コンポーネントで@ connectデコレーターも使用できます。以下のようなので:
@connect(state => ({
locale: state.locale,
currentUser: state.currentUser
}))
class App extends React.Component
これらはすべて小道具として渡され、接続はアプリのどこでも使用できます。スプレッド演算子でグローバルな小道具を渡すことをお勧めしますが
<Navbar {...this.props} />
アプリ内の他のすべてのコンポーネント(または「ページ」)は、独自のカプセル化された状態を実行できます。たとえば、[ユーザー]ページで独自の操作を実行できます。
class Users extends React.Component {
constructor(props) {
super(props);
this.state = {
loadingUsers: false,
users: [],
};
}
......
ロケールとcurrentUserは、コンテナコンポーネントから渡されるため、小道具を介してアクセスします。
このアプローチは私がそれを複数回やったことで機能します。
しかし、React=子どもたち。
欠点:
これらの欠点は、管理するのが少し退屈で面倒です。それがReduxが構築された理由です。
私が助けてくれたことを願っています。幸運を
Reduxを使用することで、このようなコールバックを回避し、1つのストアで全体の状態を維持できます-したがって、親コンポーネントを接続コンポーネントにし、左右のコンポーネントをダムコンポーネントにし、親から子に取得した小道具を渡すだけで、この場合、コールバックについて心配する必要はありません。