Redux:根据 Actions 改变 Reducer 中初始状态的不同部分
Redux: altering different parts of the initial state in Reducer according to Actions
我有以下 Reducer:
const initialState = {}
const dishReducer = (state = initialState, action) => {
switch (action.type) {
case 'LOAD_DISHES':
return (action.dishes)
case 'LOAD_DISHES_ERROR':
console.log("load dishes error")
return state
case 'LOAD_DISHES_SUCCESS':
console.log("load dishes success")
return state
default:
return state;
}
};
export default dishReducer;
以及以下操作:
import {database} from '../../config/fbConfig'
export const startLoadingDishes = (dishes) => {
return (dispatch) =>{
return database.ref('products-dishes').once('value').then((snapshot) => {
let dishes = {}
snapshot.forEach((childSnapshot) => {
let parentkey = childSnapshot.key
let dishArray = [];
childSnapshot.forEach((dish) =>{
dishArray.push(dish.val())
});
dishes[childSnapshot.key] = dishArray;
})
dispatch(loadDishes(dishes))
}).then(() => {
dispatch({ type: 'LOAD_DISHES_SUCCESS' });
}).catch(err => {
dispatch({ type: 'LOAD_DISHES_ERROR' }, err);
});
}
}
export const loadDishes = (dishes) => {
return {
type: 'LOAD_DISHES',
dishes
}
}
'startLoadingDishes'动作在某个Component的componentDidLoad()内部被调用。但是,我想改变我的 dishReducer 的初始状态,以便它包含额外的信息,如下所示:
const initialState = {
value : {},
loaded: false,
loading: false,
error: false
}
所以现在 reducer [在 'LOAD_DISHES' 情况下] 返回的 'action.dishes' 应该放在状态的 'value' 部分,而不是整个状态。此外,如果盘子已经加载较早,则状态的 'loaded' 部分应设置为 true,依此类推。我知道这很简单,但由于我是 React+Redux 的新手,我不知道如何正确更改 Action/Reducer 代码(同时保持状态不变性)。感谢任何帮助。
我最初问这个问题,这是我解决它的方法(虽然不确定这是否是 'best' 方式):
新减速器文件:
const initialState = {
value : {},
loaded: false,
loading: false,
error: false
}
const dishReducer = (state = initialState, action) => {
switch (action.type) {
case 'LOAD_DISHES':
return {
value: action.dishes,
loading: !state.loading,
loaded: false, //this might need to be set to true
error: false
}
case 'LOAD_DISHES_ERROR':
console.log("load dishes error")
return {
...state, //or: state.value, as the other parts of state are being overwritten below
loaded: false,
loading: false,
error: true
}
case 'LOAD_DISHES_SUCCESS':
console.log("load dishes success")
return {
...state, //better: state.value
loaded: true,
loading: false,
error: false
}
default:
return state;
}
};
export default dishReducer;
动作文件没有变化。
现在,在 'Main' 组件中,我最初是这样访问状态的:
class Main extends Component {
componentDidMount() {
this.props.startLoadingDishes();
}
render() {
return (
//some code
)
}
}
const mapStateToProps = (state) => {
return {
dishes: state.dishes //to access dishes: dishes.value
}
}
export default connect(mapStateToProps, actions)(Main)
主要组件代码也保持不变,不同之处在于现在我使用 'dishes.value' 而不是 'dishes' 从状态访问菜肴的价值(和 dishes.loaded加载等)。现在 componentDidMount 中的 action caller 如下:
componentDidMount() {
if(!this.props.dishes.loaded){
this.props.startLoadingDishes();
console.log("loading dishes from database")
}
}
我有以下 Reducer:
const initialState = {}
const dishReducer = (state = initialState, action) => {
switch (action.type) {
case 'LOAD_DISHES':
return (action.dishes)
case 'LOAD_DISHES_ERROR':
console.log("load dishes error")
return state
case 'LOAD_DISHES_SUCCESS':
console.log("load dishes success")
return state
default:
return state;
}
};
export default dishReducer;
以及以下操作:
import {database} from '../../config/fbConfig'
export const startLoadingDishes = (dishes) => {
return (dispatch) =>{
return database.ref('products-dishes').once('value').then((snapshot) => {
let dishes = {}
snapshot.forEach((childSnapshot) => {
let parentkey = childSnapshot.key
let dishArray = [];
childSnapshot.forEach((dish) =>{
dishArray.push(dish.val())
});
dishes[childSnapshot.key] = dishArray;
})
dispatch(loadDishes(dishes))
}).then(() => {
dispatch({ type: 'LOAD_DISHES_SUCCESS' });
}).catch(err => {
dispatch({ type: 'LOAD_DISHES_ERROR' }, err);
});
}
}
export const loadDishes = (dishes) => {
return {
type: 'LOAD_DISHES',
dishes
}
}
'startLoadingDishes'动作在某个Component的componentDidLoad()内部被调用。但是,我想改变我的 dishReducer 的初始状态,以便它包含额外的信息,如下所示:
const initialState = {
value : {},
loaded: false,
loading: false,
error: false
}
所以现在 reducer [在 'LOAD_DISHES' 情况下] 返回的 'action.dishes' 应该放在状态的 'value' 部分,而不是整个状态。此外,如果盘子已经加载较早,则状态的 'loaded' 部分应设置为 true,依此类推。我知道这很简单,但由于我是 React+Redux 的新手,我不知道如何正确更改 Action/Reducer 代码(同时保持状态不变性)。感谢任何帮助。
我最初问这个问题,这是我解决它的方法(虽然不确定这是否是 'best' 方式):
新减速器文件:
const initialState = {
value : {},
loaded: false,
loading: false,
error: false
}
const dishReducer = (state = initialState, action) => {
switch (action.type) {
case 'LOAD_DISHES':
return {
value: action.dishes,
loading: !state.loading,
loaded: false, //this might need to be set to true
error: false
}
case 'LOAD_DISHES_ERROR':
console.log("load dishes error")
return {
...state, //or: state.value, as the other parts of state are being overwritten below
loaded: false,
loading: false,
error: true
}
case 'LOAD_DISHES_SUCCESS':
console.log("load dishes success")
return {
...state, //better: state.value
loaded: true,
loading: false,
error: false
}
default:
return state;
}
};
export default dishReducer;
动作文件没有变化。
现在,在 'Main' 组件中,我最初是这样访问状态的:
class Main extends Component {
componentDidMount() {
this.props.startLoadingDishes();
}
render() {
return (
//some code
)
}
}
const mapStateToProps = (state) => {
return {
dishes: state.dishes //to access dishes: dishes.value
}
}
export default connect(mapStateToProps, actions)(Main)
主要组件代码也保持不变,不同之处在于现在我使用 'dishes.value' 而不是 'dishes' 从状态访问菜肴的价值(和 dishes.loaded加载等)。现在 componentDidMount 中的 action caller 如下:
componentDidMount() {
if(!this.props.dishes.loaded){
this.props.startLoadingDishes();
console.log("loading dishes from database")
}
}