Object is possibly 'null': TypeScript, React useRef & Formik innerRef
Asked Answered
R

3

7

In my React/TypeScript app that uses Formik, I am getting the error

Object is possibly 'null'.  TS2531

    125 |             <Modal.Footer>
  > 126 |                 <Button variant="primary" type="submit" form="nicknameForm" disabled={!(formRef.current.isValid && formRef.current.dirty)}>Apply</Button>
        |                                                                                            ^
    127 |             </Modal.Footer>
    128 |         </Modal>
    129 |     )

Tried changing formRef.current.isValid to formRef!.current.isValid and formRef.current.dirty to formRef!.current.dirty but the error persists.

Why is this so, and how can we fix this error? Thank you!

import React, { useState, useEffect, useRef } from 'react';
import { Button, Modal, Form } from 'react-bootstrap';
import { Formik } from 'formik';

interface IModal {
    show: boolean;
    handleClose: () => void;
}

export function NicknameModal({show, handleClose}: IModal) {

    const formRef = useRef(null);

    return (
        <Modal show={show} onHide={handleClose}>
            <Modal.Header closeButton>
                <Modal.Title>My Title</Modal.Title>
            </Modal.Header>
            <Modal.Body>
                <Formik
                    initialValues={{
                        nickname: '',
                    }}
                    innerRef={formRef}
                    onSubmit={(
                        values,
                        { setSubmitting }
                    ) => {
                        setSubmitting(true);
                        handleClose();
                        setSubmitting(false);
                    }}
                >
                    {({values, errors, touched, handleChange, handleBlur, handleSubmit, isSubmitting, setFieldValue }) => (
                        <Form id="nicknameForm" onSubmit={handleSubmit}>
                            <Form.Group controlId="formNickname">
                                <Form.Label>Nickname</Form.Label>
                                <Form.Control type="text" name="nickname" onChange={handleChange} onBlur={handleBlur} value={values.nickname} />
                            </Form.Group>
                        </Form>  
                    )}
                </Formik>
            </Modal.Body>
            <Modal.Footer>
                <Button variant="primary" type="submit" 
                 disabled={!(formRef.current.isValid && formRef.current.dirty)}
                 form="nicknameForm">Apply</Button>
            </Modal.Footer>
        </Modal>
    )
}

UPDATE:

If const formRef = useRef(null); is changed to const formRef = useRef();, we now encounter a different error:

Type 'MutableRefObject<undefined>' is not assignable to type '((instance: FormikProps<{ nickname: string; }> | null) => void) & MutableRefObject<undefined>'.
  Type 'MutableRefObject<undefined>' is not assignable to type '(instance: FormikProps<{ nickname: string; }> | null) => void'.
    Type 'MutableRefObject<undefined>' provides no match for the signature '(instance: FormikProps<{ nickname: string; }> | null): void'.  TS2322

    71 |                         nickName: '',
    72 |                     }}
  > 73 |                     innerRef={formRef}
       |                     ^
    74 |                     onSubmit={(
    75 |                         values: Values,
    76 |                         { setSubmitting }: FormikHelpers<Values>

Resonant answered 10/2, 2021 at 21:17 Comment(2)
You definitely need to set the generic on your useRef but I have to look up what the appropriate type would be for the innerRef of a Formik.Threecolor
Does Formik even have an innerRef prop? Field does: formik.org/docs/api/field#innerref but I am not seeing it documented on Formik formik.org/docs/api/formikThreecolor
O
17

You need to set type for useRef, where FormValues is your form values

type FormValues = {};
useRef<FormikProps<FormValues>>(null);

https://github.com/formium/formik/issues/2600#issuecomment-693479057

Oran answered 26/3, 2021 at 10:34 Comment(4)
(null) can be missed easily, but very important.Brendabrendan
... And if you are seeing this because you want to reset the form here is a one-liner that will make formik and yourself happy: const formikRef = useRef<FormikProps<Record<string, unknown>>>(null);Foxed
I was struggling so long. I just missed (null) and was wondering why its still reporting. ThanksZawde
Don't forget to add <any> to your Formik component: <Formik> => <Formik<any>>Gosney
M
2

Try with:

import { FormikProps } from "formik";

const formRef = useRef<FormikProps<any>>(null);
Murat answered 31/3, 2022 at 8:37 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Laforge
E
0

First of all you need to define a type for Formik initial values:

interface FormnameInitialValues {
  destination_city: string;
  cell_phone: string;
}

const initialValues: FormnameInitialValues = {
  cell_phone: "",
  destination_city: "",
};

Then define a form type for the ref state and set your form initial values type to it:

import { FormikProps } from "formik";

const formikRef = useRef<FormikProps<FormnameInitialValues>>(null);

Now you can use all the properties of Formik from the ref state without any typescript errors and also get the benefit of autocomplete.

if (formikRef.current) formikRef.current.resetForm();
if (formikRef.current) formikRef.current.isValid();
Ene answered 30/4 at 20:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.