useNumberInput hook in Chackra with Formik

Viewed 837

the problem is that for some reason, the increment and decrement buttons do not affect the final value in the input, but when you directly enter the value in the input, the value changes.

import { Box, Button, FormControl, FormErrorMessage, FormLabel, HStack, Input, useNumberInput } from '@chakra-ui/react';
import { Field, useField } from 'formik';
import React from 'react';

interface TextInputProps{
    name: string;
    label: string;
}

const CountInput: React.FC<TextInputProps> = ({ name, label}) => {
    const [field, { error, touched }] = useField(name);
    const {
        getInputProps,
        getIncrementButtonProps,
        getDecrementButtonProps,
    } = useNumberInput({
        step: 1,
        defaultValue: 1,
        min: 1,
        max: 10,
        precision: 0,
    })

    const inc = getIncrementButtonProps();
    const dec = getDecrementButtonProps();
    const input = getInputProps({ ...field });


    return (
        <Field name={name}>
            {({ form }: any) => {
                return (
                    <FormControl isInvalid={form.errors[name] && form.touched[name]}>
                        <FormLabel htmlFor={name}>{label}</FormLabel>
                        {description && <Box mb={5}>{description}</Box>}
                        <HStack maxW="320px">
                            <Button {...dec}>-</Button>
                            <Input id={name} onChange={(val) => form.setFieldValue(field.name, val)} {...input} />
                            <Button {...inc}>+</Button>
                        </HStack>
                        <FormErrorMessage>{form.errors[name]}</FormErrorMessage>
                    </FormControl>
                );
            }}
        </Field>
    );
}

export default CountInput;

I am guessing that the problem is with passing the property spread ...field to getInputProps(), which in turn resets the value.

2 Answers

Pass onChange to useNumberInput after the ...field spread as follows:

const [field, meta, helpers] = useField(name);
const { getInputProps, getIncrementButtonProps, getDecrementButtonProps } =
useNumberInput({
  ...field,
  onChange: (valueAsString, valueAsNumber) => helpers.setValue(valueAsNumber),
});

because the onChange parameter of useNumberInput expects

(method) UseCounterProps.onChange?(valueAsString: string, valueAsNumber: number): void

while the onChange of field from useField has a different signature.

what is the content of field?

I am also trying to use the useNumberInput hook in Chakra, the get input props only accepts some values and here they are

export declare function useNumberInput(props?: UseNumberInputProps): {
    value: React.ReactText;
    valueAsNumber: number;
    isFocused: boolean;
    isDisabled: boolean | undefined;
    isReadOnly: boolean | undefined;
    getIncrementButtonProps: PropGetter<any, {}>;
    getDecrementButtonProps: PropGetter<any, {}>;
    getInputProps: PropGetter<any, {}>;
    htmlProps: {
        defaultValue?: string | number | undefined;
        value?: string | number | undefined;
    };
};
Related