Как мне написать эти функции, чтобы отправка завершалась до запуска операторов if? В настоящее время операторы if запускают console.info() до того, как отправка может даже сохранить данные.
const doStuff = () => {
dispatch(getStuff()); // WAIT FOR ME TO COMPLETE BEFORE MOVING ON!!!
if (stuff) { //stuff is retreived from global state
console.info("stuff available") //I WAITED FOR THE DISPATCH!
}
if (!stuff) { //stuff is retreived from global state
console.info("no stuff") //I WAITED FOR THE DISPATCH!
}
};
export const getStuff = () => { \\WAIT FOR ME TO SAVE STUFF!!!
return (dispatch) => {
axios.get(`/stuff`).then((response) => {
dispatch({
type: SAVE_STUFF_TO_STATE, //stuff is saved to global state
payload: response.data, //stuff
});
})
} catch (err) {
console.info("stuff issue")
}
};
};
@MetallimaX Материал сохраняется в состояние через редуктор.
И как восстановить состояние?
@MetallimaX Материал извлекается из состояния с помощью useSelector.
почему бы вам не использовать для этого useEffect?
@buzatto что это изменит? Я также пробовал это, и это ничего не дало, кроме создания дополнительных шагов.
потому что вы можете запустить код, который вам нужно передать как зависимость stuff
. он будет работать только на stuff
обновлениях
@buzatto Я только что попробовал, ничего не изменилось, как ожидалось.
@buzatto Мой фактический код запускает оверлейное сообщение об ошибках. Во время функции doStuff(), если отправка завершается без ошибок, операторы if должны выполняться после. Если функция отправки сохраняет данные в состояние, то операторы if будут запускать наложение ошибок, если данных нет.
Вернуть промис можно из функции, можно попробовать с помощью https://github.com/reduxjs/redux-thunk
enter code hereexport const getStuff = () => { \\WAIT FOR ME TO SAVE STUFF!!!
return (dispatch) => {
axios.get(`/stuff`).then((response) => {
return Promise.resolve(
// the actions to be dispatched goes here
);
})
} catch (err) {
console.info("stuff issue")
}
};
};
и дождитесь его выполнения,
const doStuff = () => {
dispatch(getStuff()).then(()=> { // WAIT FOR ME TO COMPLETE BEFORE MOVING ON!!!
if (stuff) { //stuff is retreived from global state
console.info("stuff available") //I WAITED FOR THE DISPATCH!
}
if (!stuff) { //stuff is retreived from global state
console.info("no stuff") //I WAITED FOR THE DISPATCH!
}
});
};
В общем, если вы хотите связать определенные действия (согласно вашему примеру) с отправкой, ваше действие должно будет вернуть обещание
Я пробовал это, прежде чем задавать этот вопрос, но я попробовал еще раз для удовольствия, и это не сработало. Я получаю сообщение об ошибке: Невозможно прочитать свойство "тогда" неопределенного. Я читал об этом, потому что функции отправки ничего не возвращают, поэтому у них не может быть .then().
Вам нужно вернуть обещание от getStuff: return axios.get(/stuff
).then
@HMR Я только что попытался добавить возврат к аксиомам, обещаниям и отправке по отдельности, ни один из них не сработал. Тот, который вы указали, сломал код, каким-то образом остановив функцию отправки в обещании. Остальные пришли с той же исходной ошибкой.
@ user67 Я добавил рабочий пример, если вы не можете заставить его работать, предоставьте песочницу, демонстрирующую проблему.
@HMR хорошо, спасибо, сейчас я смотрю и понимаю ваш пример.
@user67. я предполагал, что вы используете преобразователь, так как вы использовали отправку при возврате внутри функции. Если вы этого не сделали, вам может понадобиться избыточный преобразователь, чтобы улучшить ваши функции для возврата действия.
@SasiKumarM В моих модулях установлен redux-thunk. Я смотрю на альтернативные варианты, такие как сага. Кажется, что .then() ничего не возвращает. Спасибо.
я забыл добавить возврат к обещанию. редукционный преобразователь определенно сработает в этом сценарии, stackoverflow.com/questions/35069212/…
Ваша функция создания обещания должна возвращать обещание, и ваше действие thunk должно возвращать это обещание:
const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const initialState = {
status: 'initial',
};
//action types
const ONE = 'ONE';
const TWO = 'TWO';
//action creators
const later = (value, time = 2000) =>
new Promise((resolve) =>
setTimeout(() => resolve(value), time)
);
const one = () => (dispatch) =>
//return the promise here
later()
.then(() => dispatch({ type: ONE }))
.then(() => later('the value one resolves with'));
const two = () => ({ type: TWO });
const reducer = (state, { type, payload }) => {
if (type === ONE) return { ...state, status: 'one' };
if (type === TWO) return { ...state, status: 'two' };
return state;
};
//selectors
const selectStatus = (state) => state.status;
//creating store with redux dev tools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
initialState,
composeEnhancers(
applyMiddleware(
({ dispatch, getState }) => (next) => (action) =>
//basic thunk implementation
typeof action === 'function'
? action(dispatch, getState)
: next(action)
)
)
);
const App = () => {
const dispatch = useDispatch();
React.useEffect(() => {
one()(dispatch).then((oneResolve) => {
console.info('one resolved with:', oneResolve);
dispatch(two());
});
}, [dispatch]);
const status = useSelector(selectStatus);
return <h1>Status:{status}</h1>;
};
ReactDOM.render(
<Provider store = {store}>
<App />
</Provider>,
document.getElementById('root')
);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id = "root"></div>
Как вещи «набиваются»?