checklist field: use reducer for state
This commit is contained in:
parent
c577348edf
commit
204a4c02d1
|
@ -66,7 +66,7 @@ skulk({
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
debug: false,
|
debug: true,
|
||||||
entryFile: "settings",
|
entryFile: "settings",
|
||||||
outputFile: "settings.js",
|
outputFile: "settings.js",
|
||||||
prodCfg: prodCfg,
|
prodCfg: prodCfg,
|
||||||
|
|
|
@ -20,8 +20,14 @@
|
||||||
|
|
||||||
const React = require("react");
|
const React = require("react");
|
||||||
const syncpipe = require("syncpipe");
|
const syncpipe = require("syncpipe");
|
||||||
|
const { createSlice } = require("@reduxjs/toolkit");
|
||||||
|
|
||||||
function createState(entries, uniqueKey, oldState, defaultValue) {
|
const { reducer, actions } = createSlice({
|
||||||
|
name: "checklist",
|
||||||
|
initialState: {},
|
||||||
|
reducers: {
|
||||||
|
create: (state, { payload }) => {
|
||||||
|
const { entries, uniqueKey, defaultValue } = payload;
|
||||||
return syncpipe(entries, [
|
return syncpipe(entries, [
|
||||||
(_) => _.map((entry) => {
|
(_) => _.map((entry) => {
|
||||||
let key = entry[uniqueKey];
|
let key = entry[uniqueKey];
|
||||||
|
@ -30,37 +36,34 @@ function createState(entries, uniqueKey, oldState, defaultValue) {
|
||||||
{
|
{
|
||||||
...entry,
|
...entry,
|
||||||
key,
|
key,
|
||||||
checked: oldState[key]?.checked ?? entry.checked ?? defaultValue
|
checked: state[key]?.checked ?? entry.checked ?? defaultValue
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}),
|
}),
|
||||||
(_) => Object.fromEntries(_)
|
(_) => Object.fromEntries(_)
|
||||||
]);
|
]);
|
||||||
}
|
},
|
||||||
|
updateAll: (state, { payload: value }) => {
|
||||||
function updateAllState(state, newValue) {
|
|
||||||
return syncpipe(state, [
|
return syncpipe(state, [
|
||||||
(_) => Object.values(_),
|
(_) => Object.values(_),
|
||||||
(_) => _.map((entry) => [entry.key, {
|
(_) => _.map((entry) => [entry.key, {
|
||||||
...entry,
|
...entry,
|
||||||
checked: newValue
|
checked: value
|
||||||
}]),
|
}]),
|
||||||
(_) => Object.fromEntries(_)
|
(_) => Object.fromEntries(_)
|
||||||
]);
|
]);
|
||||||
}
|
},
|
||||||
|
update: (state, { payload: { key, value } }) => {
|
||||||
function updateState(state, key, newValue) {
|
state[key] = {
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
[key]: {
|
|
||||||
...state[key],
|
...state[key],
|
||||||
...newValue
|
...value
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = function useCheckListInput({ name }, { entries, uniqueKey = "key", defaultValue = false }) {
|
module.exports = function useCheckListInput({ name }, { entries, uniqueKey = "key", defaultValue = false }) {
|
||||||
const [state, setState] = React.useState({});
|
const [state, dispatch] = React.useReducer(reducer, {});
|
||||||
|
|
||||||
const [someSelected, setSomeSelected] = React.useState(false);
|
const [someSelected, setSomeSelected] = React.useState(false);
|
||||||
const [toggleAllState, setToggleAllState] = React.useState(0);
|
const [toggleAllState, setToggleAllState] = React.useState(0);
|
||||||
|
@ -71,11 +74,13 @@ module.exports = function useCheckListInput({ name }, { entries, uniqueKey = "ke
|
||||||
entries changed, update state,
|
entries changed, update state,
|
||||||
re-using old state if available for key
|
re-using old state if available for key
|
||||||
*/
|
*/
|
||||||
setState(createState(entries, uniqueKey, state, defaultValue));
|
dispatch(actions.create({ entries, uniqueKey, defaultValue }));
|
||||||
|
|
||||||
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
||||||
}, [entries]);
|
}, [entries]);
|
||||||
|
|
||||||
|
console.log(state);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
/* Updates (un)check all checkbox, based on shortcode checkboxes
|
/* Updates (un)check all checkbox, based on shortcode checkboxes
|
||||||
Can be 0 (not checked), 1 (checked) or 2 (indeterminate)
|
Can be 0 (not checked), 1 (checked) or 2 (indeterminate)
|
||||||
|
@ -105,6 +110,7 @@ module.exports = function useCheckListInput({ name }, { entries, uniqueKey = "ke
|
||||||
}
|
}
|
||||||
}, [state, toggleAllRef]);
|
}, [state, toggleAllRef]);
|
||||||
|
|
||||||
|
return React.useMemo(() => {
|
||||||
function toggleAll(e) {
|
function toggleAll(e) {
|
||||||
let selectAll = e.target.checked;
|
let selectAll = e.target.checked;
|
||||||
|
|
||||||
|
@ -112,12 +118,16 @@ module.exports = function useCheckListInput({ name }, { entries, uniqueKey = "ke
|
||||||
selectAll = false;
|
selectAll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(updateAllState(state, selectAll));
|
dispatch(actions.updateAll(selectAll));
|
||||||
setToggleAllState(selectAll);
|
setToggleAllState(selectAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
setState(updateAllState(state, defaultValue));
|
dispatch(actions.updateAll(defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(key, value) {
|
||||||
|
dispatch(actions.update({ key, value }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectedValues() {
|
function selectedValues() {
|
||||||
|
@ -134,7 +144,7 @@ module.exports = function useCheckListInput({ name }, { entries, uniqueKey = "ke
|
||||||
], {
|
], {
|
||||||
name,
|
name,
|
||||||
value: state,
|
value: state,
|
||||||
onChange: (key, newValue) => setState(updateState(state, key, newValue)),
|
onChange,
|
||||||
selectedValues,
|
selectedValues,
|
||||||
reset,
|
reset,
|
||||||
someSelected,
|
someSelected,
|
||||||
|
@ -144,4 +154,5 @@ module.exports = function useCheckListInput({ name }, { entries, uniqueKey = "ke
|
||||||
onChange: toggleAll
|
onChange: toggleAll
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}, [defaultValue, name, someSelected, state, toggleAllState]);
|
||||||
};
|
};
|
Loading…
Reference in New Issue