如果从 props 传递,则处理 useReducer
handle useReducer if pass from props
我正在尝试针对特定用例在组件中对 useReducer
进行可覆盖的使用。
下面是我的overfly简化工作状态:
function defaultToggleReducer (state, action) {
console.log('Default toggler used')
return !state
}
function customTogglerReducer (state, action) {
console.log('Custom toggler used')
return !state
}
// Dummy wrap to log the initialization from `Togller` component to point the twice initializations
function toggleInitializer (state) {
console.log('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
和呈现 Toggler
并提供减速器的 DefaultToggler
。
如果您需要标准切换器,请使用 DefaultToggler
,如果您需要自定义版本,请使用哑 Toggler
,并提供自定义缩减器。
function defaultToggleReducer (state, action) {
console.log('Default toggler used')
return !state
}
function customTogglerReducer (state, action) {
console.log('Custom toggler used')
return !state
}
// Dummy wrap to log the initialization from `Togller` component to point the twice initializations
function toggleInitializer (state) {
console.log('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" />
我正在尝试针对特定用例在组件中对 useReducer
进行可覆盖的使用。
下面是我的overfly简化工作状态:
function defaultToggleReducer (state, action) {
console.log('Default toggler used')
return !state
}
function customTogglerReducer (state, action) {
console.log('Custom toggler used')
return !state
}
// Dummy wrap to log the initialization from `Togller` component to point the twice initializations
function toggleInitializer (state) {
console.log('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
和呈现 Toggler
并提供减速器的 DefaultToggler
。
如果您需要标准切换器,请使用 DefaultToggler
,如果您需要自定义版本,请使用哑 Toggler
,并提供自定义缩减器。
function defaultToggleReducer (state, action) {
console.log('Default toggler used')
return !state
}
function customTogglerReducer (state, action) {
console.log('Custom toggler used')
return !state
}
// Dummy wrap to log the initialization from `Togller` component to point the twice initializations
function toggleInitializer (state) {
console.log('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" />