同じ質問がありましたが、私の設定ではうまく動作する方法が見つかったようです。私はNode、Express、React、React Router、ReduxとRedux Thunkを使います。
1)本当にデータの場所によって異なります。 /member/:memberId
に必要なデータが既に状態にある場合(例えば、以前の呼び出しから)、componentDidMount
が起動されたときに、既に持っているものをフィルタリングすることができます。
しかし、私は頭痛を避けるために物事を分けておくことを好むでしょう。アプリケーション全体で複数の目的地/目的に1つのデータソースを使用すると、長い時間がかかる場合があります(たとえば、の場合、コンポーネントAはより多くの/少ないプロパティをコンポーネントBまたはのコンポーネントAに必要です) のコンポーネントBなどとは異なる形式)。
この決定は当然あなたのユースケースに基づいているべきですが、APIコールのコストのために、誰かが/member/:memberId
にナビゲートするとき、私は恐らく(全く)恐れることはありません。
2)私は典型的なセットアップの簡易版でお答えします:リクエストが伝わってくるたびに、私はこのやつはそれを処理してい
。
// Imports and other jazz up here
app.use((req, res) => {
const store = configureStore({});
const routes = createRoutes(store);
match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
if (error) {
res.status(500).send(error.message);
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else if (renderProps) {
const fetchedData = renderProps.components
.filter(component => component.fetchData)
.map(component => component.fetchData(store, renderProps.params));
Promise.all(fetchedData).then(() => {
const body = renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
);
res.status(200).send(`<!doctype html>${renderToStaticMarkup(
<Html
body={body}
state={store.getState()}
/>)
}`);
});
} else {
res.status(404).send('Not found');
}
});
});
これは、レンダリングされようとしているコンポーネントにfetchData
を探して、私たちはクライアントに何かを送信する前に、我々はデータを持っていることを確認します。
各ルートには、Container
があります。 Container
の唯一の目的は、そのルートに必要なデータを収集することです。あなたが触れたように、サーバ側(私の場合はfetchData
)またはクライアント側(私の場合はcomponentDidMount
)が発生する可能性があります。 Container
で
// Imports up here
class Container extends Component {
static fetchData(store, params) {
const categories = store.dispatch(getCategories());
return Promise.all([categories]);
}
componentDidMount() {
this.props.dispatch(getCategoriesIfNeeded());
}
render() {
return this.props.categories.length ? (
// Render categories
) : null;
}
}
Container.propTypes = {
categories: PropTypes.array.isRequired,
dispatch: PropTypes.func.isRequired,
params: PropTypes.object.isRequired,
};
function mapStateToProps(state) {
return {
categories: state.categories,
};
}
export default connect(mapStateToProps)(Container);
私はルートのデータを必要としていることを確認するgetCategories
とgetCategoriesIfNeeded
を使用しています上記:私の典型的なContainer
は次のようになります。 getCategories
はサーバ側と呼ばれ、getCategoriesIfNeeded
はクライアント側と呼ばれます。私は潜在的に:memberId
のようなものを抽出するために使用することができます(connect()
から渡される)の両方fetchData
とcomponentDidMount
、ために利用可能なparams
を持って
注意。
上記のデータをフェッチするために使用される二つの機能を以下に示します。私はRedux Thunkへdispatch
とgetState
両方利用できるおかげで持っている上に表示したよう
// Using this for structure of reducers etc.:
// https://github.com/erikras/ducks-modular-redux
//
// actionTypes object and reducer up here
export function getCategories() {
return (dispatch, getState) => {
dispatch({
type: actionTypes.GET_REQUEST,
});
return fetch('/api/categories').then(res => {
return !res.error ? dispatch({
error: null,
payload: res.body,
type: actionTypes.GET_COMPLETE,
}) : dispatch({
error: res.error,
payload: null,
type: actionTypes.GET_ERROR,
});
});
};
}
export function getCategoriesIfNeeded() {
return (dispatch, getState) => {
return getState().categories.length ? dispatch(getCategories()) : Promise.resolve();
};
}
- あまりにも私の約束を扱う - データを使用して、私に自由を与えます私はすでに新しいデータを要求して、私のレデューサーの複数の更新を行います。
私はこれがあなたを動かすのに十分であることを望みます。それ以上の説明を躊躇しないでください:)
偉大な答え。私が使っている実装がこのプロジェクトから出てくるようです:https://github.com/caljrimmer/isomorphic-redux-app。彼らはあなたと同様のアプローチを使用しますが、コンポーネントで静的関数を使用する代わりに、アクション作成者を呼び出します。私が欠けていたのは、ルータに結び付けられているため、アクション作成者がクエリーパラメータを渡して、要求されているレコードを照会することができます。 – nicholas
甘い、私が助けることができてうれしい:) – marcfalk