Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Cannot pass props object to React+typescript component

Sorry if this seems really obvious, but I’ve been trying to figure out for two days now. I’m writing a simple unit test in vitest that renders a component to screen and then calling screen.debug(). The test is

describe('Login unit tests', () => {
    it('renders to screen', () => {
        const loginProps = {
            handleSubmit: (e: MouseEvent<HTMLButtonElement>) => Promise.resolve(console.log('handleSubmit')),
            usernameProps: {
                value: "",
                placeholder: "Username",
                onChange: (e: ChangeEvent<HTMLInputElement>) => console.log('changeEvent'),
                type: "text"
            },
            passwordProps: {
                value: "",
                placeholder: "Password",
                onChange: (e: ChangeEvent<HTMLInputElement>) => console.log('changeEvent'),
                type: "password" 
            },
            isHidden: true,
        }
        render(<Login {...loginProps} />);
        screen.debug();
    })
})

The function definitions are just stand-ins with correct type, but would most likely be a vi.fn(). The component definition including interface of prop object is

interface LoginProps {
    handleSubmit: (e: MouseEvent<HTMLButtonElement>) => Promise<void>,
    usernameProps: InputProps,
    passwordProps: InputProps,
    isHidden: boolean,
}

const Login = ({
    handleSubmit,
    usernameProps,
    passwordProps,
    isHidden
}: LoginProps) => {
    return (
        <div className="login-container">
            <div className="login-bounding-box">
                <div className="login-title">Login</div>
                <form className="login-form">
            <input {...usernameProps} />
            <input {...passwordProps} />
            <button type="submit" onClick={handleSubmit}>Login</button>
        </form>
                <div className="error-msg" hidden={isHidden}>Username/password incorrect.</div>
                <div className="signup-msg">
                    Don't have an account? Sign up <Link to="/signup">here</Link>.
                </div>
            </div>
        </div>
    )
}

After running npm run test I get the following error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

TypeError: Cannot destructure property 'basename' of 'React__namespace.useContext(...)' as it is null.
 ❯ LinkWithRef node_modules/react-router-dom/index.tsx:427:11
 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:16305:18
 ❯ updateForwardRef node_modules/react-dom/cjs/react-dom.development.js:19226:20
 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21636:16
 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27426:14
 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26560:12
 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26466:5
 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26434:7
 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25850:20
 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25750:22

The interface for InputProps is

export default interface InputProps {
    value: string;
    placeholder: string | undefined;
    onChange: (e: ChangeEvent<HTMLInputElement>) => void;
    type: string;
}

I know the error is coming from the render(<Login />) line, but the error is cryptic and I’m not sure how to proceed. I assume there’s something wrong with how I’m passing in the props object to <Login /> but I can’t seem to figure out.

>Solution :

You’re probably wrapping a Router (like a BrowerRouter or MemoryRouter) somewhere in your app.
But for the tests, the component is rendered by itself, without the rest of the app.

In that case, it’s missing a Router, that React Router needs to find the basename property from its context.

Try rendering your test wrapped in a router, like so

import { BrowserRouter } from 'react-router-dom'
...
render(<BrowserRouter><Login {...loginProps} /></BrowserRouter>);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading