简体   繁体   中英

How to pass an object to a custom child component in ReactJS using Typescript?

Objective

I want to fetch data in App's root component via useEffect() (and set them to state) and then pass state to my custom component. I can do it with JS but the same steps don't work with Typescript.

My error message is the following:

Type '{ obj: Person; }' is not assignable to type 'IntrinsicAttributes 
& Person & { children?: ReactNode; }'. Property 'obj' does not exist 
on type 'IntrinsicAttributes & Person & { children?: ReactNode; }'.TS2322

To me, it looks like I have an object with Person type I can't assign to another type of Person...

App.tsx

import React, { useState, useEffect } from 'react';
import Profile from '../Profile';

export interface Person {
  name: string;
  email: string;
  dob: string;
  address: string;
  number: string;
  userName: string;
  pssw: string;
};

const initPerson: Person = {
  name: "",
  email: "",
  dob: "",
  address: "",
  number: "",
  userName: "",
  pssw: ""
};

const App: React.FC = () => {
  const [ profile, setProfile ] = useState<Person>(initPerson)

  useEffect(() => {
    // logic for fetching data and setting the state
  }, []);

  return (
    <div id="app">
      <h1>Random user generator</h1>
      <div id="content">
        <Profile obj={profile} />
    </div>
  );
}

export default App;

Person.tsx

import React from 'react';
import { Person } from './app/App'

const Profile: React.FC<Person> = (props) => {
    return (
        <div id="Card">
            {/* photo */}
            <div id="photo"><img src="" alt="profile" /></div>
            {/* name */}
            <div id="name"></div>
            {/* email */}
            <div id="email"></div>
            {/* dob */}
            <div id="dob"></div>
            {/* adress */}
            <div id="address"></div>
            {/* number */}
            <div id="number"></div>
            {/* pssw */}
            <div id="password"></div>
        </div>
    );
}

export default Profile;

I could not find any relevant YT video nor previous post here... Based on these questions ( here and here ) I think I need to declare the interface of my component?

If so:

  • Where?
  • Why do I need to declare the interface of my component if I have already defined interface for Person that I am passing to my component?
  • How should the declaration look like?
  • What is the error telling me?
  • How should I pass data to the child component correctly? (and also from child to parent)
  • Also is there something else I should know?

Any help is very appreciated. Thank you!

The issue is that this

const Profile: React.FC<Person>

should be this

const Profile: React.FC<{ obj: Person }>

That is, props isn't of type Person , you have a obj prop in Profile which is of type Person .

The type parameter T in React.FC<T> needs to be the shape of all your custom props, on top of the built in React ones (ie children ) - so basically an object with fields.

For instance if you had another prop foo which should be a number, it would be React.FC<{ obj: Person, foo: number }> , etc.

You are passing a prop shape that's actually

export interface Person {
  obj: {
    name: string;
    email: string;
    dob: string;
    address: string;
    number: string;
    userName: string;
    pssw: string;
  }
};

but you declared

export interface Person {
  name: string;
  email: string;
  dob: string;
  address: string;
  number: string;
  userName: string;
  pssw: string;
};

Since I see you like to learn and try things out, I'll let you figure out where the adjustment can be done, If not. let me know and I'll add more details.

You can do something like that:

// Here you create an interface for Profile component that receives an "obj" prop of Person type.
interface ProfileProps {
  obj: Person;
}

const Profile: React.FC<ProfileProps> = (props) => {
   console.log(props.obj);
   return (
   ....

And now you will be good, because when you set Profile tag in App Component you are passing the obj prop:

<Profile obj={profile} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM