从 Redux 迁移到 Redux 工具包
Migrating from Redux to Redux toolkit
我正在慢慢地从 Redux 迁移到 Redux 工具包。我还是很新,但我有这个登录操作功能。我要如何翻译下面的旧功能,我需要 createAsyncThunk
才能实现吗?
export const login = (email, password) => (dispatch) => {
dispatch(requestLogin());
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((user) => {
dispatch(responseLogin(user));
})
.catch((error) => {
dispatch(loginError());
});
};
我的授权切片看起来像这样:
const authSlice = createSlice({
name: "authSlice",
initialState: {
isLoggingIn: false,
isLoggingOut: false,
isVerifying: false,
loginError: false,
logoutError: false,
isAuthenticated: false,
user: {},
},
reducers: {
signInWithEmail: (state, action) => {
const { email, password } = action.payload;
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((response) => {
const {
uid,
email,
emailVerified,
phoneNumber,
password,
displayName,
photoURL,
} = response.user;
})
.catch((error) => {
console.log(error);
});
},
},
extraReducers: {},
});
你展示的reducer是非常错误的。 Reducer 必须永远做任何事情异步!
你不需要createAsyncThunk
,但如果你想要使用它,它会像这样:
export const login = createAsyncThunk(
'login',
({email, password}) => firebase.auth().signInWithEmailAndPassword(email, password)
);
const authSlice = createSlice({
name: "authSlice",
initialState: {
isLoggingIn: false,
isLoggingOut: false,
isVerifying: false,
loginError: false,
logoutError: false,
isAuthenticated: false,
user: {},
},
reducers: {
/* any other state updates here */
},
extraReducers: (builder) => {
builder.addCase(login.pending, (state, action) => {
// mark something as loading here
}
builder.addCase(login.fulfilled, (state, action) => {
// mark request as complete and save results
}
}
});
请注意,createAsyncThunk
只允许将一个参数传递给 thunk 动作创建者,因此它现在必须是一个具有两个字段的对象,而不是单独的参数。
让我们创建一个 productSlice.js
import { createSlice,createSelector,PayloadAction,createAsyncThunk,} from "@reduxjs/toolkit";
export const fetchProducts = createAsyncThunk(
"products/fetchProducts", async (_, thunkAPI) => {
try {
const response = await fetch(`url`); //where you want to fetch data
return await response.json();
} catch (error) {
return thunkAPI.rejectWithValue({ error: error.message });
}
});
const productsSlice = createSlice({
name: "products",
initialState: {
products: [],
loading: "idle",
error: "",
},
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchProducts.pending, (state) => {
state. products = [];
state.loading = "loading";
});
builder.addCase(
fetchProducts.fulfilled, (state, { payload }) => {
state. products = payload;
state.loading = "loaded";
});
builder.addCase(
fetchProducts.rejected,(state, action) => {
state.loading = "error";
state.error = action.error.message;
});
}
});
export const selectProducts = createSelector(
(state) => ({
products: state.products,
loading: state.products.loading,
}), (state) => state
);
export default productsSlice;
在您的 store.js
中添加 productsSlice: productsSlice.reducer
in out store reducer。
然后为了在组件中使用添加这些代码...我也更喜欢使用 hook
import { useSelector, useDispatch } from "react-redux";
import { fetchProducts,selectProducts,} from "path/productSlice.js";
然后最后一部分像这样在你的主管内部调用那些方法
const dispatch = useDispatch();
const { products } = useSelector(selectProducts);
React.useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
最后,您可以在组件中以 products
的形式访问数据。
我正在慢慢地从 Redux 迁移到 Redux 工具包。我还是很新,但我有这个登录操作功能。我要如何翻译下面的旧功能,我需要 createAsyncThunk
才能实现吗?
export const login = (email, password) => (dispatch) => {
dispatch(requestLogin());
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((user) => {
dispatch(responseLogin(user));
})
.catch((error) => {
dispatch(loginError());
});
};
我的授权切片看起来像这样:
const authSlice = createSlice({
name: "authSlice",
initialState: {
isLoggingIn: false,
isLoggingOut: false,
isVerifying: false,
loginError: false,
logoutError: false,
isAuthenticated: false,
user: {},
},
reducers: {
signInWithEmail: (state, action) => {
const { email, password } = action.payload;
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((response) => {
const {
uid,
email,
emailVerified,
phoneNumber,
password,
displayName,
photoURL,
} = response.user;
})
.catch((error) => {
console.log(error);
});
},
},
extraReducers: {},
});
你展示的reducer是非常错误的。 Reducer 必须永远做任何事情异步!
你不需要createAsyncThunk
,但如果你想要使用它,它会像这样:
export const login = createAsyncThunk(
'login',
({email, password}) => firebase.auth().signInWithEmailAndPassword(email, password)
);
const authSlice = createSlice({
name: "authSlice",
initialState: {
isLoggingIn: false,
isLoggingOut: false,
isVerifying: false,
loginError: false,
logoutError: false,
isAuthenticated: false,
user: {},
},
reducers: {
/* any other state updates here */
},
extraReducers: (builder) => {
builder.addCase(login.pending, (state, action) => {
// mark something as loading here
}
builder.addCase(login.fulfilled, (state, action) => {
// mark request as complete and save results
}
}
});
请注意,createAsyncThunk
只允许将一个参数传递给 thunk 动作创建者,因此它现在必须是一个具有两个字段的对象,而不是单独的参数。
让我们创建一个 productSlice.js
import { createSlice,createSelector,PayloadAction,createAsyncThunk,} from "@reduxjs/toolkit";
export const fetchProducts = createAsyncThunk(
"products/fetchProducts", async (_, thunkAPI) => {
try {
const response = await fetch(`url`); //where you want to fetch data
return await response.json();
} catch (error) {
return thunkAPI.rejectWithValue({ error: error.message });
}
});
const productsSlice = createSlice({
name: "products",
initialState: {
products: [],
loading: "idle",
error: "",
},
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchProducts.pending, (state) => {
state. products = [];
state.loading = "loading";
});
builder.addCase(
fetchProducts.fulfilled, (state, { payload }) => {
state. products = payload;
state.loading = "loaded";
});
builder.addCase(
fetchProducts.rejected,(state, action) => {
state.loading = "error";
state.error = action.error.message;
});
}
});
export const selectProducts = createSelector(
(state) => ({
products: state.products,
loading: state.products.loading,
}), (state) => state
);
export default productsSlice;
在您的 store.js
中添加 productsSlice: productsSlice.reducer
in out store reducer。
然后为了在组件中使用添加这些代码...我也更喜欢使用 hook
import { useSelector, useDispatch } from "react-redux";
import { fetchProducts,selectProducts,} from "path/productSlice.js";
然后最后一部分像这样在你的主管内部调用那些方法
const dispatch = useDispatch();
const { products } = useSelector(selectProducts);
React.useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
最后,您可以在组件中以 products
的形式访问数据。