Reactjs 使用带有useReducer/Redux还原器的回调

Reactjs 使用带有useReducer/Redux还原器的回调,reactjs,react-redux,react-hooks,Reactjs,React Redux,React Hooks,我一直在寻找“promisify”useReducer的解决方案,一旦我确定状态已根据我的调度操作进行了更改,就可以执行某些操作。我发现了一些有前途的东西,比如这个和一些类似的解决方案,它们是基于将useReducer与useffect相结合。因此,我没有使用承诺,而是尝试使用回调,我想在这里指出,这个实现是有效的。但我不确定这是否有任何缺点 **注意,这里的用例不是每次状态改变都调用一个函数,而是当reducer处理完一个动作时做一些事情的选项 根据Redux规则,我的reducer不会改变状

我一直在寻找“promisify”
useReducer
的解决方案,一旦我确定状态已根据我的调度操作进行了更改,就可以执行某些操作。我发现了一些有前途的东西,比如这个和一些类似的解决方案,它们是基于将
useReducer
useffect
相结合。因此,我没有使用承诺,而是尝试使用回调,我想在这里指出,这个实现是有效的。但我不确定这是否有任何缺点

**注意,这里的用例不是每次状态改变都调用一个函数,而是当reducer处理完一个动作时做一些事情的选项

根据Redux规则,我的reducer不会改变状态

const emptyState: IState = {
  str: '',
  obj: {
    propA: 0,
    propB: 0,
  }
}

interface ReducerActions {
  type: 'changeStr' | 'changeObj';
  callback?: (newState: IState) => any;
}

const reducer = (state: IState, action: ReducerActions): IState => {
  let newState = {...state};
  switch(action.type) {
    case 'changeStr':
      newState.str = action.newStr;
      break;
    case 'changeObj':
      newState.obj = action.newObj;
      break;
  if (action.callback) {
    action.callback(newState);
  }
  return newState;
}

我注意到这与传统流程相反,传统流程在状态更改后执行回调或承诺,但在使用新状态的值调用回调时,这是否重要

而且,使用这种方法是否有任何缺点或副作用(无论是在这里还是在Redux实现中)

action changeStr使用两个按钮将state.str的字符串替换为新字符串,一个按钮使其变长,另一个按钮使其变短。如果我使用useEffect,我当然可以检查字符串的新值并获取长度,但是如果不存储以前的值,我将无法获取以前字符串的长度。如果我将回调传递给按钮中实现的操作,我知道哪个按钮使其变长,哪个按钮使其变短

仍然不确定您需要什么,但是如果您需要上一个和当前值来执行某些逻辑,您可以编写一个自定义挂钩:

const{useReducer,useState,useRef}=React;
const init={value:'A'};
常量切换='TOGGLE';
常量toggle=()=>({type:toggle});
const reducer=(state,{type})=>{
//在A和B之间切换state.value
如果(类型===切换){
返回{value:state.value=='A'?'B':'A'};
}
返回状态;
};
const selectValue=(state)=>state.value;
const NONE={};
//用于检测渲染之间更改的自定义挂钩
const useChange=(值,回调)=>{
const ref=useRef(无);
如果(参考电流!==值){
如果(参考电流!==无){
回调(参考当前值);
}
参考电流=值;
}
};
常量应用=()=>{
const[state,dispatch]=useReducer(reducer,init);
const[message,setMessage]=useState(“”);
常量值=选择值(状态);
useChange(值,(优先级,当前)=>
setMessage(`value已从${pref}更改为${current}`)
);
返回(
分派(切换())}>
切换
{value}
{message}
);
};
ReactDOM.render(,document.getElementById('root'))


“但无论如何,当使用新状态的值调用回调时,这应该很重要”。这不是它最初的工作原理吗?为了回答您的问题,我们可能需要更多的信息,比如您的用例是什么?如果您想在每次更新该值时使用一个回调函数,为什么不使用
useffect
?我已经为这个问题添加了一个注释,希望可以进一步澄清。我知道我可以使用useEffect,但这会在每次状态更改时触发,而不是每次调用操作时触发。基本上,用例将调用一个操作,然后在处理该操作后使用新状态执行一些操作。我可以在两个不同的地方调用changeStr,但其中一个有回调,而另一个没有。回调不必知道状态发生了什么变化。为了进一步简化,我想知道在实际设置为newState之前使用“newState”是否有副作用。使用上面的实现,回调(newState)在reducer实际返回newState之前被调用。用例实际上并不重要,因为这个实现已经完成了我想要它做的事情。相反,我想知道我的实现是否正确,它是否遵循React最佳实践(因为我知道这似乎是一种黑客方法lol)。我似乎不明白为什么你需要一个状态更新的操作,然后是一个自定义回调。无论何时更改状态,最好通过
useffect
同步更改。在调用
useffect
时,您是否关心性能?您可以在
回调中获得最新的状态,然后您可以选择以任何方式调用它,让我们这样说(当然有不同的方法来实现它,但我正在尝试使其与此实现相关),action changeStr将state.str的字符串替换为新字符串,使用两个按钮,一个使其变长,另一个变短。如果我使用useEffect,我当然可以检查字符串的新值并获取长度,但是如果不存储以前的值,我将无法获取以前字符串的长度。如果我将回调传递给在按钮中实现的操作,我知道哪个按钮使其变长,哪个按钮使其变短。不,我知道这个流(使用useffect和useRef获取以前的值)。再次重申,我想根据操作触发回调,而不是根据更改的值触发回调——在与@Rohit讨论之后,这违反了Redux规则,因为回调会带来副作用。不管怎样,谢谢你的回答@Nerdragen听起来像是你会用thunk实现的东西如果你使用Redux,useReducer不允许使用中间件,但是你可以通过用自定义钩子包装useReducer来实现thunk(参见更新的答案)。没关系,我知道useReducer不允许使用middlware。正如我前面提到的,这更多的是一个思想实验,而不是一个实际的实现问题;实际上使用Redux会破坏这个目的。我