Home > Software engineering >  Type error in react using typescript: Type '(user: User) => Element' is not assignable
Type error in react using typescript: Type '(user: User) => Element' is not assignable

Time:07-12

I am receiving the following error on the terminal, please see the attached image. The error is between two-component, I haven't worked with typescript much so it would appreciate any help I would get in solving the issue.

enter image description here

Loadable component is:

import { CircularProgress } from "@mui/material"
import { makeStyles, createStyles } from '@mui/styles';
import React, { PropsWithChildren } from "react"
import NoEntityFound from "../NoEntityFound"

const useStyles = makeStyles(
    () =>
        createStyles({
            loadingWrapper: {
                width: "100%",
                textAlign: "center",
                marginTop: 16,
            },
        }),
    { name: "Loadable" },
)

interface IProps<T> {
    error: any
    data: T | undefined
    errorMessage?: string | React.ReactNode
    renderOnError?: (node: React.ReactNode) => React.ReactNode
    children: (props: T) => any
}

const Loadable = <T,>({
    children,
    error,
    data,
    errorMessage,
    renderOnError,
}: PropsWithChildren<IProps<T>>) => {
    const defaultErrorMessage = "Entity not found!"

    const errorElement = (
        <NoEntityFound>{errorMessage || defaultErrorMessage}</NoEntityFound>
    )
    const classes = useStyles()

    if (error) {
        if (renderOnError) {
            return renderOnError(errorElement)
        }
        return errorElement
    } else if (!error && !data) {
        return (
            <div className={classes.loadingWrapper}>
                <CircularProgress />
            </div>
        )
    }

    if (typeof children !== "function") {
        console.warn("children prop must be a function!")
        return null
    }

    if (data) {
        return children(data)
    }

    return null
}

export default Loadable

Component using loadable component is:

import { Theme } from "@mui/material"
import { makeStyles, createStyles } from '@mui/styles';
import BreadcrumbBox from "components/Breadcrumb/BreadcrumbBox"
import Loadable from "components/Loadable"
import UserDetails from "components/Users/UserDetails"
import RoutingContext from "contexts/RoutingContext"
import routes from "pages/routes"
import React, { useContext, useEffect, useState } from "react"
import { useParams } from "react-router-dom"
import { getUser } from "services/Request/mpayApi"
import useSWR from "swr"
import { PathParams } from "types/routes"

import PageLayout from "../../layouts/Default"

const useStyles = makeStyles(
    (theme: Theme) =>
        createStyles({
            menuWrapper: {
                display: "flex",
                flexDirection: "column",
                height: "100%",
            },
            menuContent: {
                flexGrow: 1,
            },
        }),
    {
        name: "UserDetailsPage",
    },
)

const UserDetailsPage: React.FunctionComponent = () => {
    const [editMode, setEditMode] = useState<boolean>(false)

    const { userId = "" } = useParams<PathParams>()
    const fetcher = () => getUser(userId).then((res) => res.data)
    const { data, error, mutate } = useSWR(userId, fetcher)

    const { setParentRoute } = useContext(RoutingContext)
    useEffect(() => {
        setParentRoute(routes.users.path)
    }, [setParentRoute])

    useEffect(() => {
        // Revalidate on ticket change
        mutate(undefined, true)
    }, [editMode, mutate])

    const classes = useStyles()

    return (
        <PageLayout>
            <BreadcrumbBox>
                <Loadable error={error} data={data}>
                    {(user) => (
                        <UserDetails
                            editMode={editMode}
                            setEditMode={setEditMode}
                            user={user}
                        />
                    )}
                </Loadable>
            </BreadcrumbBox>
        </PageLayout>
    )
}

export default UserDetailsPage

Now I couldn't figure out what's going wrong if you can help me understand and solve this, it would be great. Thanks in advance!!

CodePudding user response:

Problem:

Because you wrap the props with PropsWithChildren, it will turn out children: (props: T) => any to children: (props: T) => any & React.ReactNode.

Please checkout this enter image description here

Solution:

  • Simply remove PropsWithChildren from the props to keep your defination.
  • Related