能否将Promise作为Redux状态的一部分?业务场景需求问询
Absolutely, this approach is totally feasible and can make your questionnaire flow way cleaner—let’s break down why it works and how to implement it step by step.
Yes! While Redux’s official docs recommend keeping state serializable (since serialized state can be persisted, logged, or replayed), storing a Promise is totally acceptable for specific use cases like yours—where you need to defer handling an async result until a later point in your flow.
The key caveat here is that Promises can’t be serialized (so you’ll want to exclude them if you’re using state persistence tools like redux-persist), but for in-memory state management during your questionnaire flow, this pattern simplifies things drastically: you don’t have to manually track separate loading, error, and data states—you can leverage the Promise’s inherent pending/fulfilled/rejected status directly.
Redux Toolkit is the standard way to write Redux these days, so we’ll use it to build out your scenario: Q3 → trigger API call → store the Promise → use its result in Q7.
1. Define Your Redux Slice
First, create a slice to hold user answers and the API Promise:
import { createSlice } from '@reduxjs/toolkit'; const initialState = { userAnswers: {}, // Stores answers for Q1-Q6 apiCallPromise: null, // Will hold the Promise from the Q3-triggered API call }; const questionnaireSlice = createSlice({ name: 'questionnaire', initialState, reducers: { // Save a user's answer to a specific question saveAnswer: (state, action) => { const { questionId, answer } = action.payload; state.userAnswers[questionId] = answer; }, // Store the API call Promise in state setApiCallPromise: (state, action) => { state.apiCallPromise = action.payload; }, }, }); export const { saveAnswer, setApiCallPromise } = questionnaireSlice.actions; export default questionnaireSlice.reducer;
2. Trigger the API Call After Q3
In your Q3 component, when the user submits their answer, save it to state and dispatch the Promise from your API call:
import { useDispatch } from 'react-redux'; import { saveAnswer, setApiCallPromise } from './questionnaireSlice'; // Assume this is your API function that returns a Promise import { fetchUserRelatedData } from './api'; const Q3Component = () => { const dispatch = useDispatch(); const handleSubmit = (userAnswer) => { // Save Q3's answer first dispatch(saveAnswer({ questionId: 'Q3', answer: userAnswer })); // Trigger the API call and store the Promise in Redux const apiPromise = fetchUserRelatedData(userAnswer); dispatch(setApiCallPromise(apiPromise)); // No need to handle the result here—we'll do that in Q7! }; // Render your Q3 input/submit button here return ( <div> <h2>Q3: [Your Question Text]</h2> {/* Input element for answer */} <button onClick={() => handleSubmit(userAnswer)}>Submit</button> </div> ); };
3. Use the Promise Result in Q7
In your Q7 component, pull the Promise from Redux state and handle its resolved/rejected status:
import { useSelector } from 'react-redux'; import { useState, useEffect } from 'react'; const Q7Component = () => { const apiPromise = useSelector(state => state.questionnaire.apiCallPromise); const [apiResult, setApiResult] = useState(null); const [apiError, setApiError] = useState(null); useEffect(() => { // Only process if we have a Promise that hasn't been handled yet if (apiPromise) { apiPromise .then(result => { setApiResult(result); // Optional: Clear the Promise if you don't need it anymore // dispatch(setApiCallPromise(null)); }) .catch(error => { setApiError(error); console.error('API call failed:', error); }); } }, [apiPromise]); // Render Q7 content along with API result/error return ( <div> <h2>Q7: [Your Question Text]</h2> {/* Show API result or error */} {apiError && <p className="error-message">Oops, failed to load data: {apiError.message}</p>} {apiResult && <div className="api-result"> <h3>API Data:</h3> <p>{JSON.stringify(apiResult)}</p> </div>} {/* Q7 input/submit logic */} </div> ); };
Key Considerations
- State Persistence: If you’re using
redux-persistto save state to local storage, addapiCallPromiseto theblacklistso it doesn’t get serialized (since Promises can’t be stored as JSON):import { persistReducer } from 'redux-persist'; import storage from 'redux-persist/lib/storage'; const persistConfig = { key: 'root', storage, blacklist: ['apiCallPromise'], // Exclude the Promise from persistence }; const persistedReducer = persistReducer(persistConfig, questionnaireReducer); - Avoid Duplicate Calls: If users navigate back to Q3 and resubmit, this will overwrite the existing Promise. If you want to prevent that, add a check in the
handleSubmitfunction to see ifapiCallPromisealready exists in state. - Uncaught Errors: Always include a
.catch()when handling the Promise in Q7 to avoid uncaught rejection warnings.
内容的提问来源于stack exchange,提问作者Vladyslav Zavalykhatko

