Я пытаюсь переопределить использование useReducer
в компоненте для конкретных случаев использования.
Следуя моему упрощенному рабочему режиму работы overfly:
function defaultToggleReducer (state, action) {
console.info('Default toggler used')
return !state
}
function customTogglerReducer (state, action) {
console.info('Custom toggler used')
return !state
}
// Dummy wrap to log the initialization from `Togller` component to point the twice initializations
function toggleInitializer (state) {
console.info('toggleInitializer')
return state
}
function Toggler (props) {
const [
toggleState,
toggleDispatch,
] = React.useReducer(defaultToggleReducer, false, toggleInitializer)
// Here is the prt making the previous `useReducer` useless
const state = props.toggleState !== undefined ? props.toggleState : toggleState
const dispatch = props.toggleDispatch || toggleDispatch
return (
<button
type = "button"
onClick = {() => dispatch({ type: 'add' })}>
{Boolean(state).toString()}
</button>
)
}
function App () {
const [customToggleState, customToggleDispatch] = React.useReducer(
customTogglerReducer,
false
)
return (
<div>
<fieldset>
<legend>Default</legend>
<Toggler />
</fieldset>
<fieldset>
<legend>Customized</legend>
<Toggler
toggleState = {customToggleState}
toggleDispatch = {customToggleDispatch} />
<button
type = "button"
onClick = {() => customToggleDispatch({ type: 'parentAction' })}>
This is why I want dispatch
</button>
</fieldset>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "root" />
Здесь что-то плохо пахнет, я не сомневаюсь, что это работает, но тот факт, что useReducer
вызывается в Toggler
, даже если не используется, вызывает у меня подозрения. Так что, я думаю, это мертвый редуктор.
Итак, мой вопрос:
Был ли у вас способ правильно получить управление reduce
из родительского компонента (по крайней мере: лучше, чем это)?
Воспользуйтесь составом компонентов, чтобы решить эту проблему. Разбейте Toggler
на два компонента - тупой Toggler
, который ожидает внешний редуктор, и DefaultToggler
, который отображает Toggler
и поставляет редуктор.
Если вам нужен стандартный переключатель, используйте DefaultToggler
, а если вам нужна специальная версия, используйте тупой Toggler
и предоставьте собственный редуктор.
function defaultToggleReducer (state, action) {
console.info('Default toggler used')
return !state
}
function customTogglerReducer (state, action) {
console.info('Custom toggler used')
return !state
}
// Dummy wrap to log the initialization from `Togller` component to point the twice initializations
function toggleInitializer (state) {
console.info('toggleInitializer')
return state
}
function Toggler ({ toggleState: state, toggleDispatch: dispatch }) {
return (
<button
type = "button"
onClick = {() => dispatch({ type: 'add' })}>
{Boolean(state).toString()}
</button>
)
}
function DefaultToggler () {
const [
toggleState,
toggleDispatch,
] = React.useReducer(defaultToggleReducer, false, toggleInitializer)
return (
<Toggler
toggleState = {toggleState}
toggleDispatch = {toggleDispatch}
/>
);
};
function App () {
const [customToggleState, customToggleDispatch] = React.useReducer(
customTogglerReducer,
false
)
return (
<div>
<fieldset>
<legend>Default</legend>
<DefaultToggler />
</fieldset>
<fieldset>
<legend>Customized</legend>
<Toggler
toggleState = {customToggleState}
toggleDispatch = {customToggleDispatch} />
<button
type = "button"
onClick = {() => customToggleDispatch({ type: 'parentAction' })}>
This is why I want dispatch
</button>
</fieldset>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "root" />
Пожалуйста. Если включение некоторых функций в состав компонента усложняет использование, извлеките функциональные возможности в другой компонент или в настраиваемую ловушку и используйте композицию. Контекст обычно хорош как своего рода внедрение зависимостей и позволяет избежать детализации, чего здесь нет.
Да, поэтому я не слишком много исследую таким образом. Примечание: композиция была (и до сих пор) в ключевом слове, я был уверен в этом, это именно то, что я искал :) К вашему сведению: Моя последняя работа включает ToggleBuilder
с различными компонентами (конечно, это не компонент Toggle, а скорее Accordion с дизайн безумные особенности) Еще раз спасибо!
О да, в этом есть смысл! Я думал о переносе в сложном контексте, а затем использовать Consumer blabla ... но это проще. Спасибо !