1

这是来自的示例:https ://reactjs.org/docs/hooks-reference.html#usereducer

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

在此示例中,reducer函数的引用在各个渲染中保持不变。

我可以这样做以在每次渲染时重新创建 reducer 函数吗?

const initialState = {count: 0};

function Counter() {

  // REDUCER FUNCTION WILL BE RECREATED ON EVERY RENDER

  function reducer(state, action) {
    switch (action.type) {
      case 'increment':
        return {count: state.count + 1};
      case 'decrement':
        return {count: state.count - 1};
      default:
        throw new Error();
    }
  }

  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

动机:

我正在研究货币转换器,我的减速器取决于THOUSAND_SEPARATORandDECIMAL_SEPARATOR是点.或逗号,,这可能会在渲染之间发生变化,所以我需要在每次渲染时重新创建它。

片段

它似乎有效,但它是一种反模式吗?

function App() {

  const initialState = {count: 0};

  const [bool,setBool] = React.useState(false);

  function reducer(state, action) {
    switch (action.type) {
      case 'increment':
        return {count: bool ? state.count - 1 : state.count + 1};
      case 'decrement':
        return {count: bool ? state.count + 1 : state.count - 1};
      default:
        throw new Error();
    }
  }

  const [state,dispatch] = React.useReducer(reducer, initialState);

  return (
    <React.Fragment>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => setBool((prevState) => !prevState)}>Invert Direction</button>
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

4

1 回答 1

1

这种方法很好。

据我了解,即使函数对象被多次创建,JavaScript 引擎也非常擅长重用函数体。主要区别在于,在渲染函数内部定义的函数将引用一个额外的闭包(在渲染函数中声明的变量),因此它的效率会降低一些。但是由于您需要它来引用组件的状态,因此这是一个合理的解决方案。

于 2020-05-15T16:06:47.267 回答