我正处于理解 redux 状态管理的学习阶段,并且仍在尝试在令人眼花缭乱的样板代码和中间件丛林中进行谈判,其中大部分我认为是“良药”。所以我希望你能容忍我这个可能是基本的问题。
我知道这redux-thunk允许动作创建者异步进行并在随后的时间调度常规动作。例如,我可以在我的中定义一个 thunk 动作创建者actions.js:
export function startTracking() {
return (dispatch => {
someAsyncFunction().then(result => dispatch({
type: types.SET_TRACKING,
location: result
}))
})
}
Run Code Online (Sandbox Code Playgroud)
并从 React 组件中调用它,如下所示:
onPress={() => this.props.dispatch(actions.startTracking())}
Run Code Online (Sandbox Code Playgroud)
我的问题是,与简单地从异步回调内部调度操作相比,上面的代码有什么优势?
import { store } from '../setupRedux'
...
export function startTracking() {
someAsyncFunction().then(result => {
store.dispatch({
type: types.SET_TRACKING,
location: result
})
})
}
Run Code Online (Sandbox Code Playgroud)
我会在我的组件中调用它
onPress={() => actions.startTracking()}
Run Code Online (Sandbox Code Playgroud)
甚至
onPress={actions.startTracking}
Run Code Online (Sandbox Code Playgroud)
store正如我在第二个示例中所做的那样,通过导入直接访问有什么问题吗?
要求:
如果用户申请了一个职位,则将apply_job标志传递给后端,然后将用户带到职位页面,如果apply_job标志为true,则阻止用户访问其他页面。即使用户刷新页面,如果 Applied_job 标志为 true,仍然会将用户重定向到作业页面。
问题是我使用高阶函数或高阶组件来进行路由保护,我不知道如何调用 api 来获取标志。
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => {
return (
true //assume this flag is from server, how to do an api call here??
? <Redirect to='/jobs' {...props} />
: <Component {...props} />
)
}} />
)
Run Code Online (Sandbox Code Playgroud)
https://codesandbox.io/s/6rrlz3xpz
如果我在外面打电话,应该去哪里打电话?我可以将标志存储在本地存储中,但如果是这样,用户可以从客户端删除它,这也是不对的。
我正在开发一个 React+Redux 应用程序。我通过 Redux 操作调用 API 并将响应数据存储在 Redux 状态中。但有一种情况,我不必将 API 响应数据存储在 Redux 存储中。
所以问题是,是否有任何有效的理由通过 Redux 操作调用 API,或者我应该直接调用 API,因为我没有将响应数据存储在 Redux 存储中?
我在通过 redux-thunk 使用 Redux 4.0 的新 TS 绑定时遇到问题。我通过将基本的 Redux “待办事项列表”示例转换为 TypeScript(此处为repo),并使 Add Todo 操作成为 thunk来重新创建该问题。问题与此处报告的问题相同:“ThunkAction”类型的参数不可分配给“AnyAction”类型的参数。类型 'ThunkAction' 中缺少属性 'type'。
基本上,我可以让它工作,但我any在几个我认为不应该使用的地方使用它。一个地方是index.tsx#L14,我将 thunk 中间件添加到存储中:
const store = createStore(
rootReducer,
applyMiddleware(thunk as ThunkMiddleware<IRootState, any>)
);
Run Code Online (Sandbox Code Playgroud)
如果我使用除此之外的任何其他内容any,则下一行会引发错误:
store.dispatch(addTodo('Use redux-thunk'));
Run Code Online (Sandbox Code Playgroud)
另一个地方是AddTodo.tsx#L7,我在这里声明了由connect函数注入的 dispatch prop :
interface IAddTodoProps {
dispatch: Dispatch<any>;
}
const AddTodo = ({ dispatch }: IAddTodoProps) => {
...
}
export default connect()(AddTodo);
Run Code Online (Sandbox Code Playgroud)
在这两个地方,都any覆盖了一个必须扩展的类型 …
我正在阅读createAsyncThunk文档,并对流程感到有点困惑。这是来自文档:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { userAPI } from './userAPI'
// First, create the thunk
const fetchUserById = createAsyncThunk(
'users/fetchByIdStatus',
async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId)
return response.data
}
)
// Then, handle actions in your reducers:
const usersSlice = createSlice({
name: 'users',
initialState: { entities: [], loading: 'idle' },
reducers: {
// standard reducer logic, with auto-generated action types per reducer
},
extraReducers: {
// Add reducers for additional …Run Code Online (Sandbox Code Playgroud) 我在将extraReducer添加到 createSlice时收到上述错误。
这是一个反应本机应用程序
这是我的代码:
export const login = createAsyncThunk(
'loginAuth/login',
async ({username, password}) => {
try {
const res = await api.post('SomeApi', {
username,
password,
});
return res.data;
} catch (e) {
return console.error(e.message);
}
},
);
const loginSlice = createSlice({
name: 'loginAuth',
initialState: {
loginStatus: false,
isLoading: false,
error: '',
},
reducers: {
//Yet to be filled
},
extraReducers: {
[login.pending]: (state) => {
state.isLoading = true;
},
[login.fulfilled]: (state, action) => {
state.isLoading = false;
}, …Run Code Online (Sandbox Code Playgroud) 我正在从 Redux 迁移到 Redux Toolkit。我这里的简化代码是使用 lodash/debounce 进行去抖更新。
import debounce from "lodash/debounce";
const updateApplication = async (app, dispatch) => {
const state = getState();
try {
const result = await update(app);
dispatch({
type: UPDATE,
result: result
});
} catch (err) {
console.log(err);
}
};
export default debounce(updateThunk, 2000);
Run Code Online (Sandbox Code Playgroud)
问题是当我转到 createAsyncThunk 时它不会被执行。
const updateApp = createAction("app/update");
const updateApplication = createAsyncThunk(
"app/updateDebounced",
async (app, { dispatch }) => {
try {
const result = await update(app);
dispatch(updateApp(result))
);
}
} catch (err) { …Run Code Online (Sandbox Code Playgroud) 我正在使用Redux Toolkit (RTK) 和 Redux Toolkit Query (RTK-Query)。
在任何情况下仍然使用 是最佳实践、必要还是建议thunks,或者我应该将所有逻辑移至组件中?(handleLogin()如下所示)
const Login = () => {
const dispatch = useDispatch()
const [formState, setFormState] = useState({ name: '', password: '' })
const [login, { isLoading }] = useLoginMutation()
const { push } = useHistory()
const handleLogin = async () => {
try {
const user = await login(formState).unwrap()
dispatch(setCredentials(user));
} catch (e) {
console.error(e)
}
}
return (
<div>
<input type="text" name="name" placeholder="name" />
<input type="password" …Run Code Online (Sandbox Code Playgroud) 我对整个 React 和 Redux 生态系统相当陌生,我试图了解在使用 Redux 工具包时何时以及为何使用额外的减速器,而不是直接在异步 thunk 中分派操作。
最好用一个显示这两种解决方案的示例来解释:
auth.slice.ts
// ...
export const login = createAsyncThunk<LoginResponse, LoginData>(
'auth/login',
async ({ email, password }, thunkAPI) => {
const data = await AuthService.login(email, password);
// Extract user info from login response which holds other information as well
// in which we're not interested in the auth slice...
const userInfo = loginResponseToUserInfo(data);
LocalStorageService.storeUserInfo(userInfo);
// Return the whole login response as we're interested in the other data
// besides the …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 RTK 查询通过异步函数设置 contactSlice.ts 的初始状态。
我已阅读文档并在线搜索,但没有找到解决此问题的合适解决方案。
联系人API.ts:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { Contact } from '../models/contact.model';
export const contactsApi = createApi({
reducerPath: "contactsApi",
baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:3006/" }),
tagTypes: ['Contact'],
endpoints: (builder) => ({
contacts: builder.query<Contact[], void>({
query: () => '/contacts',
providesTags: ['Contact']
}),
contact: builder.query<Contact, string>({
query: (id) => `/contacts/${ id }`,
providesTags: ['Contact']
}),
addContact: builder.mutation<{}, Contact>({
query: contact => ({
url: '/contacts',
method: 'POST',
body: contact
}),
invalidatesTags: ['Contact']
}),
updateContact: builder.mutation<void, Contact>({ …Run Code Online (Sandbox Code Playgroud)redux-thunk ×10
redux ×9
react-redux ×7
reactjs ×7
javascript ×2
react-native ×2
rtk-query ×1
typescript ×1