Я думаю, что @Duc_Hong ответил на вопрос.
И, на мой взгляд, я предлагаю использовать промежуточное программное обеспечение для побочных эффектов, чтобы сделать вызов AJAX более структурированным, чтобы мы могли обрабатывать более сложные сценарии (например, отменить запрос ajax, несколько запросов одновременно) и сделать его более проверяемый.
Вот фрагмент кода с использованием Redux Saga
// Actions.js
const FOO_FETCH_START = 'FOO\FETCH_START'
function action(type, payload={}) {
return {type, payload};
}
export const startFetch = () => action{FOO_FETCH_START, payload);
// reducer.js
export const foo = (state = {status: 'loading'}, action) => {
switch (action.type) {
case FOO_FETCH_STARTED: {
return _.assign({}, state, {status: 'start fetching', foo: null});
}
case FOO_FETCH_SUCCESS: {
return _.assign({}, state, {status: 'success', foo: action.data});
}
......
}
};
- Можно ли разместить запрос на выборку в файле Action или Reducer?
// Saga.js, Я помещаю здесь вызов ajax (fetch, axios, что вы хотите) .
export function* fetchFoo() {
const response = yield call(fetch, url);
yield put({type: FOO_FETCH_SUCCESS, reponse.data});
}
// This function will be used in `rootSaga()`, it's a listener for the action FOO_FETCH_START
export function* fooSagas() {
yield takeEvery(FOO_FETCH_START, fetchFoo);
}
- Могу ли я написать функцию в компоненте для выполнения асинхронного вызова?
// Реагировать на компонент, Я запускаю выборку созданием действия в componentDidMount
class Foo extends React.Component {
componentDidMount() {
this.props.startFetch();
}
render() {
<div>
{this.props.foo.data ? this.props.foo.data : 'Loading....'}
<div>
}
}
const mapStateToProps = (state) => ({foo: state.foo});
const mapDispatchToProps = { startFetch }
export default connect(mapStateToProps, mapDispatchToProps) (Foo);
// client.js, связывают саги, редуксы и компоненты React
const render = App => {
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
combinedReducers,
initialState,
composeEnhancers(applyMiddleware(sagaMiddleware))
);
store.runSaga(rootSaga);
return ReactDOM.hydrate(
<ReduxProvider store={store}>
<BrowserRouter><AppContainer><App/></AppContainer></BrowserRouter>
</ReduxProvider>,
document.getElementById('root')
);
}