* chore: rename APIs and Microservices to include "Backend" (#42515) * fix typo * fix typo * undo change * Corrected grammar mistake Corrected a grammar mistake by removing a comma. * change APIs and Microservices cert title * update title * Change APIs and Microservices certi title * Update translations.json * update title * feat(curriculum): rename apis and microservices cert * rename folder structure * rename certificate * rename learn Markdown * apis-and-microservices -> back-end-development-and-apis * update backend meta * update i18n langs and cypress test Co-authored-by: Shaun Hamilton <shauhami020@gmail.com> * fix: add development to front-end libraries (#42512) * fix: added-the-word-Development-to-front-end-libraries * fix/added-the-word-Development-to-front-end-libraries * fix/added-word-development-to-front-end-libraries-in-other-related-files * fix/added-the-word-Development-to-front-end-and-all-related-files * fix/removed-typos-from-last-commit-in-index.md * fix/reverted-changes-that-i-made-to-dependecies * fix/removed xvfg * fix/reverted changes that i made to package.json * remove unwanted changes * front-end-development-libraries changes * rename backend certSlug and README * update i18n folder names and keys * test: add legacy path redirect tests This uses serve.json from the client-config repo, since we currently use that in production * fix: create public dir before moving serve.json * fix: add missing script * refactor: collect redirect tests * test: convert to cy.location for stricter tests * rename certificate folder to 00-certificates * change crowdin config to recognise new certificates location * allow translations to be used Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com> * add forwards slashes to path redirects * fix cypress path tests again * plese cypress * fix: test different challenge Okay so I literally have no idea why this one particular challenge fails in Cypress Firefox ONLY. Tom and I paired and spun a full build instance and confirmed in Firefox the page loads and redirects as expected. Changing to another bootstrap challenge passes Cypress firefox locally. Absolutely boggled by this. AAAAAAAAAAAAAAA * fix: separate the test Okay apparently the test does not work unless we separate it into a different `it` statement. >:( >:( >:( >:( Co-authored-by: Sujal Gupta <55016909+heysujal@users.noreply.github.com> Co-authored-by: Noor Fakhry <65724923+NoorFakhry@users.noreply.github.com> Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com> Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com>
5.1 KiB
id, title, challengeType, forumTopicId, dashedName
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
5a24c314108439a4d4036154 | 組合多個 Reducers | 6 | 301436 | combine-multiple-reducers |
--description--
當應用程序的狀態開始變得越來越複雜時,可能會將 state 分成多個塊。 相反,請記住 Redux 的第一個原則:所有應用程序狀態都保存在 store 中的一個簡單的 state 對象中。 因此,Redux 提供 reducer 組合作爲複雜狀態模型的解決方案。 定義多個 reducer 來處理應用程序狀態的不同部分,然後將這些 reducer 組合成一個 root reducer。 然後將 root reducer 傳遞給 Redux createStore()
方法。
爲了將多個 reducer 組合在一起,Redux 提供了combineReducers()
方法。 該方法接受一個對象作爲參數,在該參數中定義一個屬性,該屬性將鍵與特定 reducer 函數關聯。 Redux 將使用給定的鍵值作爲關聯狀態的名稱。
通常情況下,當它們在某種程度上是獨一無二的,爲每個應用程序的 state 創建一個 reducer 是一個很好的做法。 例如,在一個帶有用戶身份驗證的記筆記應用程序中,一個 reducer 可以處理身份驗證而另一個處理用戶提交的文本和註釋。 對於這樣的應用程序,可能會編寫 combineReducers()
方法,如下所示:
const rootReducer = Redux.combineReducers({
auth: authenticationReducer,
notes: notesReducer
});
現在,notes
鍵將包含與註釋相關聯的所有狀態,並由 notesReducer
處理。 這就是組合多個 reducer 來管理更復雜的應用程序狀態的方式, 在此示例中,Redux store 中保存的狀態將是一個包含 auth
和 notes
屬性的簡單對象。
--instructions--
代碼編輯器中提供了 counterReducer()
和 authReducer()
函數以及 Redux store。 使用 Redux.combineReducers()
方法編寫完成 rootReducer()
函數。 將 counterReducer
分配給一個叫做 count
的鍵,將 authReducer
分配給一個叫做 auth
的鍵。
--hints--
counterReducer
應該遞增和遞減 state
。
assert(
(function () {
const initialState = store.getState().count;
store.dispatch({ type: INCREMENT });
store.dispatch({ type: INCREMENT });
const firstState = store.getState().count;
store.dispatch({ type: DECREMENT });
const secondState = store.getState().count;
return firstState === initialState + 2 && secondState === firstState - 1;
})()
);
authReducer
應該可以使 authenticated
的 state
值在 true
和 false
之間切換。
assert(
(function () {
store.dispatch({ type: LOGIN });
const loggedIn = store.getState().auth.authenticated;
store.dispatch({ type: LOGOUT });
const loggedOut = store.getState().auth.authenticated;
return loggedIn === true && loggedOut === false;
})()
);
store state
應該有兩個 key:一個是 count
,它包含一個數字。 另一個 auth
,它包含一個對象。 auth
對象應該具有 authenticated
的屬性,該屬性的值應該爲布爾值。
assert(
(function () {
const state = store.getState();
return (
typeof state.auth === 'object' &&
typeof state.auth.authenticated === 'boolean' &&
typeof state.count === 'number'
);
})()
);
rootReducer
應該是一個合併了 counterReducer
和 authReducer
的函數。
(getUserInput) =>
assert(
(function () {
const noWhiteSpace = __helpers.removeWhiteSpace(getUserInput('index'));
return (
typeof rootReducer === 'function' &&
noWhiteSpace.includes('Redux.combineReducers')
);
})()
);
--seed--
--seed-contents--
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
const counterReducer = (state = 0, action) => {
switch(action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
default:
return state;
}
};
const LOGIN = 'LOGIN';
const LOGOUT = 'LOGOUT';
const authReducer = (state = {authenticated: false}, action) => {
switch(action.type) {
case LOGIN:
return {
authenticated: true
}
case LOGOUT:
return {
authenticated: false
}
default:
return state;
}
};
const rootReducer = // Define the root reducer here
const store = Redux.createStore(rootReducer);
--solutions--
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
const counterReducer = (state = 0, action) => {
switch(action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
default:
return state;
}
};
const LOGIN = 'LOGIN';
const LOGOUT = 'LOGOUT';
const authReducer = (state = {authenticated: false}, action) => {
switch(action.type) {
case LOGIN:
return {
authenticated: true
}
case LOGOUT:
return {
authenticated: false
}
default:
return state;
}
};
const rootReducer = Redux.combineReducers({
count: counterReducer,
auth: authReducer
});
const store = Redux.createStore(rootReducer);