我无法解决redux-reducer在JavaScript中的工作方式。
以下是我正在使用的示例:
<button className="btn btn-outline-success my-2 my-sm-0"
type="submit"
onClick={this.logout}
>
<a href="/">Log Out</a>
</button>
对于该减速器,其中哪一个假设是正确的?
A)触发GET_PROFILE时,它将返回“ ... state”作为初始状态,以便redux开发人员工具可以比较状态。
B)触发GET_PROFILE时,实际上只是将值填充到我未明确列出的对象中。就像返回中的样子:
const intitialState = {
profile: null,
profiles: [],
repos: [],
loading: true,
error: {},
};
export default function (state = intitialState, action) {
const { type, payload } = action;
switch (type) {
case GET_PROFILE:
return {
...state,
profile: payload,
loading: false,
};
case PROFILE_ERROR:
return {
...state,
error: payload,
loading: false,
};
default:
return state;
}
}
如果A或B为真,那么如果我不返回... state作为第一个状态,会发生什么,这会弄乱其他对象吗?
编辑:它到底返回到什么地方?
答案 0 :(得分:2)
我会说B是真的。
如果不返回状态,则处于未返回状态的数据将丢失。
函数createStore
为您提供了5个core functions的存储对象。
我认为以下三个最显着的功能是从商店中返回的:
unsubscribe
函数以取消订阅。
react-redux
,则此订阅/取消订阅逻辑为
已经使用connect
函数或
useSelector
钩子。react-redux
,也可以在connect
函数或useSelector
挂钩中处理。react-redux
,则在connect
内部处理
函数或useDispatch
钩子。不从减速器返回状态副本将导致您丢失未返回的状态。要了解原因,请查看商店的dispatch函数。
在商店的dispatch
函数内部,您将看到reassigned的变量simply returns是从减速器(或组合减速器)返回的内容。
商店source code的currentState
变量中的getState
函数。始终从此currentState
函数中检索当前状态。
因此,当您分派操作时,状态树将使用从化简器返回的内容进行更新。
这是一个小例子,说明当您从redux reducer返回状态与不返回状态时会发生什么情况。
您可以运行并重新运行该代码段。蓝色按钮将向getState
发送返回状态的副本。黄色按钮调度一个操作GET_PROFILE
,该操作返回与GET_PROFILE_NO_STATE_COPY_RETURNED
相同的对象,但没有状态副本GET_PROFILE
。
实际上,一旦您点击...state
,您将需要重新运行该代码段,因为未指定的状态属性已完全消失:)
redux状态将根据化简器返回的内容进行更新。
我从您的问题中使用了减速器:
GET_PROFILE_NO_STATE_COPY_RETURNED
const createStore = (reducer, preloadedState, enhancer) => {
if (typeof enhancer !== 'undefined') {
return enhancer(createStore)(reducer, preloadedState);
}
let currentState = preloadedState;
let listeners = [];
const getState = () => currentState;
const subscribe = listener => {
listeners.push(listener);
return () => {
listeners = listeners.filter(l => l !== listener);
};
};
// The returned from the reducer
// inside the dispatch function
// will be the new state.
// https://github.com/reduxjs/redux/blob/master/src/createStore.ts#L246
const dispatch = action => {
currentState = reducer(currentState, action);
listeners.forEach(l => l());
};
// initialize state
dispatch({});
return {
getState,
subscribe,
dispatch,
};
};
const initialState = {
profile: null,
profiles: [],
repos: [],
loading: true,
error: {},
};
// action type constants
const GET_PROFILE = 'GET_PROFILE';
const PROFILE_ERROR = 'PROFILE_ERROR';
const GET_PROFILE_NO_STATE_COPY_RETURNED = 'GET_PROFILE_NO_STATE_COPY_RETURNED';
// reducer
const reducer = (state = initialState, {
type,
payload
}) => {
switch (type) {
case GET_PROFILE:
return {
...state,
profile: payload,
loading: false,
};
case GET_PROFILE_NO_STATE_COPY_RETURNED:
return {
profile: payload,
loading: false,
};
case PROFILE_ERROR:
return {
...state,
error: payload,
loading: false,
};
default:
return state;
}
};
const store = createStore(reducer);
const render = () => {
const html = `
<p>State</p>
<pre><code>${JSON.stringify(store.getState(), null, 4)}</code></pre>
`;
document.getElementById('app').innerHTML = html;
};
store.subscribe(render);
render();
document.getElementById('get-profile').addEventListener('click', () => {
const firstName = document.getElementById('firstName').value;
const lastName = document.getElementById('lastName').value;
store.dispatch({
type: GET_PROFILE,
payload: {
firstName,
lastName,
},
});
});
document
.getElementById('get-profile-no-state-returned')
.addEventListener('click', () => {
const firstName = document.getElementById('firstName').value;
const lastName = document.getElementById('lastName').value;
store.dispatch({
type: GET_PROFILE_NO_STATE_COPY_RETURNED,
payload: {
firstName,
lastName,
},
});
});
因此,当您调度动作时,reducer返回的值将成为您的新状态。
答案 1 :(得分:1)
[B]是最正确的答案,但并不完全正确。
在每个事件(或操作类型)处,状态都将被替换。 initialState 仅与第一步有关。
如以下示例所示,当触发ADD_RECIPIENT时,将显示以下行:
recipients: [...state.recipients, recipient]
表示state.recipients是其自身的串联加上要添加的新“收件人”。 与以下过程相同:
return {
...state,
recipients: [...state.recipients, recipient]
}
状态由自身的串联代替。
示例:
const initialState = {
selectedRecipient: '',
recipients: []
};
export default function (state = initialState, action) {
switch (action.type) {
case LOAD_RECIPIENTS: {
const { recipients } = action.payload;
return {
...state,
selectedRecipient: recipients[0],
recipients: recipients
};
}
case ADD_RECIPIENT: {
const { recipient } = action.payload;
return {
...state,
recipients: [...state.recipients, recipient]
};
}
...
...
答案 2 :(得分:0)
它的作用类似于B选项。状态将用新值更新(正在使用传播运算符)。然后,将新状态发送到反应(返回将以这种方式工作)反应检查是否有任何更改,并在需要时更新DOM。模型非常简化,但接近真实。