admin管理员组

文章数量:1336632

My goal is to implement a React controlled input using the useReducer hook.

Inside the reducer I need the event.target.value and event.target.selectionStart to get the current value and caret position. So I've thought about sending the event as the payload for the ON_CHANGE action.

This is what I'm trying:

function reducer(state = "", action) {
  console.log("From reducer... action.type: " + action.type);
  switch (action.type) {
    case "ON_CHANGE": {
      const event = action.payload;
      const caretPosition = event.target.selectionStart;
      const newValue = event.target.value;
      console.log("From reducer... event.target.value: " + event.target.value);
      console.log(
        "From reducer... event.target.selectionStart: " + caretPosition
      );
      return newValue;
    }
    default: {
      return state;
    }
  }
}

export default function App() {
  console.log("Rendering App...");

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

  return (
    <div className="App">
      <input
        value={state}
        onChange={event => dispatch({ type: "ON_CHANGE", payload: event })}
      />
    </div>
  );
}

It works for the 1st letter typed, but it breaks on the 2nd.

This is the error:

Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property target on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See react-event-pooling for more information.

What should I do? Where do I need to call event.persist(). Should I do it on the reducer or I need to do it before sending it as a parameter, inside the onChange() handler.

Or is it better to send only those properties, instead of sending the full event object?

Like:

onChange={ event => 
  dispatch({ 
    type: "ON_CHANGE", 
    payload: {
      value: event.target.value,
      caretPosition: event.target.selectionStart
    }
  })
}

My goal is to implement a React controlled input using the useReducer hook.

Inside the reducer I need the event.target.value and event.target.selectionStart to get the current value and caret position. So I've thought about sending the event as the payload for the ON_CHANGE action.

This is what I'm trying:

https://codesandbox.io/s/optimistic-edison-xypvn

function reducer(state = "", action) {
  console.log("From reducer... action.type: " + action.type);
  switch (action.type) {
    case "ON_CHANGE": {
      const event = action.payload;
      const caretPosition = event.target.selectionStart;
      const newValue = event.target.value;
      console.log("From reducer... event.target.value: " + event.target.value);
      console.log(
        "From reducer... event.target.selectionStart: " + caretPosition
      );
      return newValue;
    }
    default: {
      return state;
    }
  }
}

export default function App() {
  console.log("Rendering App...");

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

  return (
    <div className="App">
      <input
        value={state}
        onChange={event => dispatch({ type: "ON_CHANGE", payload: event })}
      />
    </div>
  );
}

It works for the 1st letter typed, but it breaks on the 2nd.

This is the error:

Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property target on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See react-event-pooling for more information.

What should I do? Where do I need to call event.persist(). Should I do it on the reducer or I need to do it before sending it as a parameter, inside the onChange() handler.

Or is it better to send only those properties, instead of sending the full event object?

Like:

onChange={ event => 
  dispatch({ 
    type: "ON_CHANGE", 
    payload: {
      value: event.target.value,
      caretPosition: event.target.selectionStart
    }
  })
}
Share Improve this question asked May 16, 2020 at 10:26 cbdevelopercbdeveloper 31.5k44 gold badges200 silver badges396 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

Just pass the event.target.value instead, because like the error says, synthetic events don't persist.

function reducer(state = "", action) {
  switch (action.type) {
    case "ON_CHANGE": {
      const newValue = action.payload;
      return newValue;
    }
    default: {
      return state;
    }
  }
}

export default function App() {
  const [state, dispatch] = useReducer(reducer, "");

  return (
    <div className="App">
      <input
        value={state}
        onChange={event =>
          dispatch({ type: "ON_CHANGE", payload: event.target.value })
        }
      />
    </div>
  );
}

本文标签: javascriptHow to implement a react controlled input using useReducerStack Overflow