Berurusan dengan input nombor dalam React boleh menjadi sukar, terutamanya apabila anda perlu memastikan ia mempunyai saiz yang betul atau mempunyai bilangan titik perpuluhan yang betul. Perkara mudah mungkin kelihatan mudah, tetapi sebaik sahaja anda memahami perkara ini dan cuba mencapai pengalaman pengguna tersuai, kod itu boleh menjadi kucar-kacir dengan cepat.
Pendekatan biasa yang kebanyakan kita gunakan ialah menulis logik pengesahan tersuai yang menyekat input pengguna dalam pengendali onChange.
Sesuatu seperti ini
function NumberInput({ value, onChange, min, max, }: { value: number; onChange: (val: number) => void; min?: number; max?: number; }) { const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => { const val = +e.target.value; if (min != null && val < min) { onChange(min); return; } if (max != null && val > max) { onChange(max); return; } onChange(val); }; return ( <input type="number" value={value} onChange={changeHandler} /> ); }
Logik ini kelihatan baik pada pandangan pertama tetapi jika anda telah mencubanya, anda tahu ia datang dengan banyak tingkah laku yang tidak dijangka dan pelik dan sama sekali bukan pengalaman pengguna yang baik!
Pendekatan lain ialah menggunakan HTML standard elemen dengan pengesahan terbina menggunakan atribut seperti min, maks, maxLength dsb. Walau bagaimanapun, ia tidak mempunyai maklum balas segera dan sekatan input yang biasanya kami ingin laksanakan.
Kami akhirnya Googling ke arah Stack Overflow dan mencari beberapa... penyelesaian hackish.
Selepas banyak percubaan dan kesilapan, akhirnya saya dapati cara yang lebih baik untuk melakukan ini.
Kami boleh menggunakan pengesahan input HTML terbina dengan beberapa javascript tersuai untuk membina penyelesaian yang sempurna.
Berikut ialah komponennya
// Interface for props overriding the default value and onChange // attribute to accept only numeric value export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> { onChange: (val: number) => void; value: number; } function NumberInput({ value, onChange, min, max, step, ...props }: NumberInputProps) { // Internal input state to avoid weird behaviors with empty inputs const [input, setInput] = React.useState(value?.toString() || ""); const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => { // Using HTML input validity API to validation if ( (max != null && e.target.validity.rangeOverflow) || (min != null && e.target.validity.rangeUnderflow) || (step != null && e.target.validity.stepMismatch) ) return; const val = +e.target.value; setInput(e.target.value); onChange(val); }; // To ensure the external updates are reflected in the input element React.useEffect(() => { setInput(value.toString()); }, [value]); return ( <Input ref={ref} type="number" value={input} onChange={changeHandler} min={min} max={max} step={step} {...props} /> ); }
Dengan pendekatan ini, kami boleh menggunakan pengesahan HTML terbina dan juga menyekat input pengguna yang tidak sah untuk nombor.
Lihat contoh langsung dan main-main
Kita boleh menjadikan logik ini lebih boleh digunakan semula dengan mengeluarkannya dalam cangkuk tersuai seperti ini
export const useNumberInput = ({ value, onChange, min, max, step, }: { value: number; onChange: (val: number) => void; max?: number; min?: number; step?: number; }): InputHTMLAttributes<HTMLInputElement> => { const [input, setInput] = useState(value?.toString() || ""); const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => { if ( (max != null && e.target.validity.rangeOverflow) || (min != null && e.target.validity.rangeUnderflow) || (step != null && e.target.validity.stepMismatch) ) return; const val = +e.target.value; setInput(e.target.value); onChange(val); }; useEffect(() => { setInput(value.toString()); }, [value]); return { type: "number", value: input, onChange: changeHandler, min, max, step, }; };
Dan gunakannya dalam mana-mana komponen jika diperlukan ( Jelas sekali yang mempunyai elemen input ).
export default function CustomInput() { const [value, setValue] = useState(0); const inputProps = useNumberInput({ value, onChange: setValue, min: 1, max: 50, }); return ( <div> <button onClick={() => onChange(value + 1)}> + </button> <button onClick={() => onChange(value - 1)}> - </button> <input {...inputProps} {...otherProps} /> </div> ); }
Jangan ragu untuk menambah ulasan dan mencadangkan penambahbaikan!
Atas ialah kandungan terperinci Cara terbaik untuk mengendalikan pengesahan input nombor dalam React. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!