<TextField/> will not render value when passed a number. This happens even if `type="number"'
When a number is passed to the value prop <TextField/> should render the value
No value is rendered
https://codesandbox.io/s/shopify-polaris-textfield-number-issue-u7kve
Or run npx envinfo --system --binaries --browsers --npmPackages react,react-dom,@shopify/polaris to provide specifications on your environment including version numbers, browser, device, and operating system.
Paste the results here:
System:
OS: Windows 10 10.0.18362
CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
Memory: 2.21 GB / 15.86 GB
Binaries:
Node: 10.15.3 - C:\Program Files\nodejs\node.EXE
npm: 6.10.2 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: 44.18362.449.0
Internet Explorer: 11.0.18362.1
npmPackages:
react: ^16.12.0 => 16.12.0
react-dom: ^16.12.0 => 16.12.0
馃憢 Thanks for opening your first issue. A contributor should give feedback soon. If you haven鈥檛 already, please check out the contributing guidelines.
Looks like this was intended behavior:
https://github.com/Shopify/polaris-react/pull/2598/files#diff-ce1bd24f5c7c2bd4b9fb5d55a5aa97aeR186-R189
Same issue after updating from 4.10.2 to 4.11.0.
All the "input-type: number" textfields have stopped working at all.
TextFields just fail displaying any variables from redux store for me.
Found solution:
I have number variables in my redux store.
Before I were passing numbers directly to the textfield, and then parsing a string coming from textfield back to the number to store and work with it properly.
Now I pass my number variables to the textfield after parsing them to the string:
value={String(
this.props.boosterTable.currentItem.dismissTime
)}
Everything else is the same.
Just parse your number to the string before passing it to the TextField "value" prop.
Just parse your number to the string before passing it to the TextField "value" prop.
Yes my solution for every number input now is
const [myValue setMyValue] = useState(3)
const handleChange = useCallback((val) => setMyValue(Number(val)), [setMyValue])
<TextField value={myValue.toString()} onChange={handleChange}/>
Not ideal but some values I want stored as numbers
Heya @pklitscher,
As you've already found out TextField only supports passing a string into its value, per its type, and the solution is to call toString() on what you pass in.
It's typing has been this way for a long time and any usage of you passing a number into there that worked before v4.11.0 was due to accident rather than design.
This is because the value you get back from an onChange event on an <input> field is always a string and it would be confusing to start off with a state that is of type number, and then when an onChange event is triggered you store the value of the event target in that state, and thus change the type.
Consider the following code:
export function Playground() {
// value starts off as a number
const [value, setValue] = React.useState(3);
const changeV = React.useCallback((event) => {
console.log(typeof event.target.value, event.target.value);
setValue(event.target.value);
}, []);
return (
<input value={value} onChange={changeV} type="number" />;
);
}
Here we have an initial state that is a number (3) and we pass that through to the input value. However say you type into the input field, adding a 4. The onChange event fires and the value of event.target.value is '34' - a string not a number. This would then get persisted into your state and now your state is a string ('34'). Note that having type=number has no effect on the value of the event target - it is always a string.
TextField seeks to avoid this potential for unexpected behaviour by ensuring that the value you pass in - and the value you get back from its onChange handler - is always a string.
Maybe y'all should consider creating a new component called NumberField if your not willing to allow TextField to render a number anymore.
import React from "react";
import { TextFieldProps, TextField } from "@shopify/polaris";
const isNumber = (val: any) => !Number.isNaN(val);
interface INumberFieldProps
extends Omit<TextFieldProps, "type" | "value" | "onChange"> {
onChange(value: number, id: string): void;
value?: number;
}
export default function NumberField(props: INumberFieldProps) {
const { onChange, value, ...restProps } = props;
const valueAsString = isNumber(value) ? value!.toString() : "";
return (
<TextField
{...restProps}
type="number"
value={valueAsString}
onChange={(val, id) => {
const parsedVal = val ? parseInt(val) : null;
const isNumber = !!(parsedVal && !Number.isNaN(parsedVal));
isNumber && onChange(parsedVal as number, id);
}}
/>
);
}
Yup confirming the same issue using v4.16.1
Most helpful comment
Maybe y'all should consider creating a new component called
NumberFieldif your not willing to allowTextFieldto render a number anymore.