0

React 文档中,它说在受控组件中,“React 状态是‘单一事实来源’”。这似乎是正确的,除非在前导零的情况下。在下面的示例中,您可以看到输入受控制,但在前导零的情况下,输入值并不总是与状态值匹配。


考试

键入前导零,因此该值类似于0010.

可以看到 in 的值state是一个整数10,但是输入显示的是0010

我的第一个想法是这是因为组件实际上并没有重新渲染,这是真的。10和之间没有状态变化10,所以没有新的渲染。这得到了证实,因为我们没有看到“渲染”console.log 触发。

所以让我们确保我们改变了这个值。添加一个2以更改001000102. state 中的值现在是102,我们确认组件重新渲染......但前导零仍然存在于输入中。


这似乎不一致,因为我希望输入中的值始终与状态中的值完全匹配。为什么会这样,什么是从数字输入中修剪前导零的可靠方法?

// LEADING ZEROS INPUT TEST
// Step 1: type 0s into the input followed by any other digits
// Step 2: see that console log and val in `p` do not have leading 0's and input val does

const {useState} = React;

const App = () => {
  const [val, setVal] = useState(10);
  
  const handleChange = (evt) => {
    const strVal = evt.currentTarget.value;
    console.log('string', strVal, typeof strVal);
    const intVal = parseInt(strVal, 10) || 0; // || 0 bc '' returns NaN
    console.log('int', intVal, typeof intVal);
    setVal(intVal);
  }
  
  console.log('render', val);
  
  return (
    <div>
      <p>{val}</p>
      <input 
        type="number"
        value={val}
        onChange={handleChange}
      />
    </div>
  )
}

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

4

1 回答 1

0

由于您已经知道WHY我将帮助您解决HOW问题。

以我的拙见,从数字输入中修剪前导零的可靠方法是“模糊化”,这会减少干扰并提供更好的用户体验。

const {useState, useCallback} = React;

const App = () => {
  const [val, setVal] = useState(10);
  const [strVal, setStrVal] = useState("10"); // To keep a reference of the real input value
  
  const handleChange = (evt) => {
    const inputVal = evt.currentTarget.value;
    setStrVal(inputVal);
    setVal(parseInt(evt.currentTarget.value, 10) || 0);
  }

  const handleBlur = useCallback((evt) => {
    setStrVal(val.toString());
  }, [val]);
  
  return (
    <div>
      <p>{val}</p>
      <input
        type="number"
        value={strVal}
        onChange={handleChange}
        onBlur={handleBlur}
      />
    </div>
  )
}

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

于 2021-05-23T15:51:06.770 回答