Итак, я все еще новичок в наборе инструментов Redux и, вероятно, что-то делаю неправильно. В любом случае мне интересно, как извлечь мои «селекторы» из моего магазина/фрагмента в Redux.
Допустим, у меня есть следующий фрагмент:
const mySlice = creatSlice({
name: 'my-slice',
initialState: {
stuff: {
primary: 'Things',
secondary: 'Other Things',
},
},
reducers: (create) => ({
getStuff: create.asyncThunk(
() => getSomeDataAsynchronously(),
{ ...justAssumeTheseUpdateStateWithData },
),
}),
// this is the part I'm most interested in understanding better
// I'm not even sure I'm doing it right. Is this how to handle
// using arguments, or do I need to curry or something?
selectors: {
selectStuff: (state) => state.stuff,
selectSpecificStuff: (state, key) => state[key] ?? 'not found',
}
});
const store = configureStore({
reducer: mySlice.reducer
});
Итак, вот что меня больше всего смущает. Предположим, я внедрил это хранилище в свой Provider
и нахожусь в дочернем компоненте реакции:
import { useSelector } from 'react-redux';
const MyComponent = () => {
const selectSpecificStuff = useSelector(/* how to access from my slice? */);
return <>{selectSpecificStuff('primary')}</>;
}
Возможно ли это вообще? Кажется, я ничего не могу найти об этом в документации, что заставляет меня задаться вопросом, в чем смысл свойства selectors, если вы не можете получить к нему доступ.
Любая помощь приветствуется.
Я не пробовал селекторы внутри createSlice(). Однако без этих записей должно работать следующее:
const sliceOfInterest = useSelector(state => state['my-slice']);
и теперь вы можете получить доступ
sliceOfInterest.stuff.primary, etc.
Очевидно, вам нужно проверить, не является ли значение нулевым.
Кроме того, экспортируйте свои действия, чтобы их можно было вызывать из другого места.
// Action creators are generated for each case reducer function
export const { getStuff } = mySlice.actions;
Однако вам не нужны функции редуктора «get». Используйте функции редуктора для редактирования/изменения вашего глобального состояния. Получите к ним доступ, используя useSelector, показанный выше.
Если у вас есть другие функции-редюсеры (в той области кода, где находится getSuff), вы вызовете их следующим образом:
dispatch(getStuff(params))
Мне любопытно, как извлечь мои «селекторы» из моего магазина/фрагмента в редукс.
Селекторы извлекаются так же, как и сгенерированные действия.
Пример:
export const {
selectStuff,
selectSpecificStuff
} = myslice.selectors;
Селектор selectSpecificStuff
все еще работает с состоянием среза, поэтому сначала ему потребуется доступ к state.stuff
.
selectors: {
selectStuff: (state) => state.stuff,
selectSpecificStuff: (state, key) => state.stuff[key] ?? "not found"
}
или
selectors: {
selectStuff: (state) => state.stuff,
selectSpecificStuff: (state, key) => {
const stuff = mySlice.getSelectors().selectStuff(state);
return stuff[key] ?? "not found";
}
}
Итак, вот что меня больше всего смущает. Предположим, я ввел это store в моем
Provider
, и я нахожусь на дочернем компоненте реакции:import { useSelector } from 'react-redux'; const MyComponent = () => { const selectSpecificStuff = useSelector(/* how to access from my slice? */); return <>{selectSpecificStuff('primary')}</>; }
Возможно ли это вообще? Кажется, я ничего не могу найти об этом в docs, что заставляет меня задуматься, в чем смысл свойства selectors? есть, если вы не можете получить к нему доступ.
Часть, которая изначально сбила меня с толку в этих селекторах, заключается в том, что они генерируются с ожиданием монтирования/внедрения в хранилище с использованием определенного значения редуктора, которое по умолчанию соответствует свойству name
среза.
Пример:
import { createSlice } from '@reduxjs/toolkit';
const mySlice = createSlice({
name: 'my-slice', // <-- default reducer path
initialState: {
stuff: {
primary: 'Things',
secondary: 'Other Things',
},
},
reducers: (create) => ({
....
}),
selectors: {
selectStuff: (state) => state.stuff,
selectSpecificStuff: (state, key) => state.stuff[key] ?? "not found"
}
});
export const {
selectStuff,
selectSpecificStuff
} = myslice.selectors;
...
const store = configureStore({
reducer: {
"my-slice": mySlice.reducer // <-- mount under correct path
}
});
Импортируйте селекторы и в обратном вызове хука useSelector
передайте корневое состояние и аргумент key
селектору среза.
import { useSelector } from 'react-redux';
import { selectStuff, selectSpecificStuff } from '../path/to/mySlice';
const MyComponent = () => {
const stuff = useSelector(selectStuff);
const primaryStuff = useSelector((state) =>
selectSpecificStuff(state, "primary")
);
const secondaryStuff = useSelector((state) =>
selectSpecificStuff(state, "secondary")
);
const tertiaryStuff = useSelector((state) =>
selectSpecificStuff(state, "tertiary")
);
console.info({
stuff: // { stuff: { primary: "Things", secondary: "Other Things" } }
primaryStuff, // "Things"
secondaryStuff, // "Other Things"
tertiaryStuff, // "not found"
});
...
}
Использование mySlice.getSelectors()
— это другой способ доступа к селекторам.
const store = configureStore({
reducer: mySlice.reducer
});
import { useSelector } from 'react-redux';
import mySlice from '../path/to/mySlice';
const MyComponent = () => {
const stuff = useSelector(mySlice.getSelectors().selectStuff);
const primaryStuff = useSelector((state) =>
mySlice.getSelectors().selectSpecificStuff(state, "primary")
);
const secondaryStuff = useSelector((state) =>
mySlice.getSelectors().selectSpecificStuff(state, "secondary")
);
const tertiaryStuff = useSelector((state) =>
mySlice.getSelectors().selectSpecificStuff(state, "tertiary")
);
console.info({
stuff: // { stuff: { primary: "Things", secondary: "Other Things" } }
primaryStuff, // "Things"
secondaryStuff, // "Other Things"
tertiaryStuff, // "not found"
});
...
}