Dreaded Harvester
Dreaded Harvester

Reputation: 1547

How to pass data between functional components in React?

In React we can pass data between class based components using states and props in the following manner:

App.js

import Name from './Name';
import React, { Component } from 'react'


export class App extends Component {
  state = {
    name: "Tarun"
  }

  render() {
    return (
      <Name name={this.state.name}/>        
    )
  }
}

export default App

Name.js

import React, { Component } from 'react'

export class Name extends Component {
    render() {
        return (
            <div>
                My name is : {this.props.name}
            </div>
        )
    }
}

export default Name

But now since React has introduced functional components what is the equivalent code if I use functional components for both App.js and Name.js?

Upvotes: 28

Views: 55645

Answers (5)

user3025289
user3025289

Reputation:

If you use React v17+ with TypeScript & functional components in React.StrictMode, then:

1) Parent to Child

1.1) Parent Component, e.g. App.tsx

import Dashboard from "./components/Dashboard/Dashboard";
export default function App() {
  return <Dashboard title="My Dashboard"></Dashboard>;
}

1.2) Child Component, e.g. Dashboard

// src/components/Dashboard/Dashboard.tsx

import React from "react";

type DashboardProps = {
  title: string;
};

const Dashboard: React.FC<DashboardProps> = (props) => (
  <div>Dashboard Component {props.title}</div>
);

export default Dashboard;

This is the same as above (excerpt):

//..
export default function Dashboard(props: DashboardProps) {
  return <div>Dashboard Component {props.title}</div>;
}

Lazy-Loading

If you want to use "Lazy-Loading", you have to change the Dashboard component slightly or maybe use a Dashboard.lazy.tsx like:

import React, { lazy, Suspense } from 'react';
import { DashboardProps } from '../../Types';
const LazyDashboard = lazy(() => import('./Dashboard'));

const Dashboard = (props: DashboardProps) => (
  <Suspense fallback={null}>
    <LazyDashboard {...props} />
  </Suspense>
);

export default Dashboard;

I've moved the DashboardProps into a new file due to reusability.

// Types/index.tsx
export type DashboardProps = {
  title: string;
};

2) Child to Parent (this time with React.useState hook)

2.1) Parent, e.g. App.tsx

import Dashboard from "./components/Dashboard/Dashboard";
export default function App() {
  const [messageFromChild, getMessageFromChild] = React.useState(
    "Dad is waiting"
  );

  const sendDataToParent = (message: string) => {
    getMessageFromChild(message);
  };
  return (
    <div>
      <Dashboard
        props={{ title: "My Dear Dashboard" }}
        sendDataToParent={sendDataToParent}
      ></Dashboard>
      <div>
        <strong>From Child to Parent:</strong> {messageFromChild}
      </div>
    </div>
  );
}

2.2) Child, e.g. Dashboard.tsx

import React from "react";
import { DashboardProps } from "../../Types";

const Dashboard: React.FC<DashboardProps> = ({ props, sendDataToParent }) => (
  <div>
    <strong>From Parent to Child:</strong> {props.title}
    &nbsp;
    <button
      onClick={() => {
        sendDataToParent("Hi Dad");
      }}
    >
      Send to Parent
    </button>
  </div>
);

export default Dashboard;

2.3) Types, e.g. Types/index.tsx

export type DashboardProps = {
  props: {
    title: string;
  };
  sendDataToParent: (message: string) => void;
};

Parent is waiting Message from child

Upvotes: 9

bakar_dev
bakar_dev

Reputation: 996

You should use useState hook for state management in functional components as follows:

import React, { useState } from "react";

export default function App() {
    const [name, setName] = useState("Tarun");
    
    return (
        <div>
             <Name name={name}/>
        </div>
    );
}


//Name
export default function Name(props) {
    return (
        <div>
            My name is : {props.name}
        </div>
    );
}

Upvotes: 0

norbitrial
norbitrial

Reputation: 15166

For Name.jsx you could do something like the following:

import React from 'react';

// additionally you can do destructuring with props like this:
// const Name = ({name}) => {
const Name = (props) => {
    return (
        <div>
            My name is : {props.name}
        </div>
    );
}

export default Name;

Passing props happens at creation time of the functional component just like above. As the React documentation states:

This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “function components” because they are literally JavaScript functions.

You can read further here: Function and Class Components

For App.jsx let me suggest the following example:

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

const App = () => {
    const [name, setName] = useState('Tarun');

    return (
        <Name name={name}/>        
    )
}

export default App;

From the above example useState function is the state hook what helps you create state object in your App.jsx functional component and for further updates you can use the setName function additionally for example on a click event. From the documentation:

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.

Please refer this link Using the State Hook.

I hope this helps!

Upvotes: 5

Luis Edward Miranda
Luis Edward Miranda

Reputation: 43

App.js

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

export function App(){
    const [name, setName] = "Tarun";
    return <Name name={name}>;
}

Name.js

import React, { Component } from 'react'

export function Name({name}){
   return <div>My name is : {name} </div>
}

There you go.

Upvotes: 0

Andy
Andy

Reputation: 63524

Using hooks you could write something like this.

In App:

import React, { useState } from 'react'

export default function App() {

  // `useState` returns an array with the state
  // and the method used to update the state
  // You can initialise the state with a variable/object
  const [name, setName] = useState('Tarun');

  // No need for a render method
  // Just return the JSX from the function
  return <Name name={name} />;
}

In Name:

import React from 'react'

// Props are passed down like normal function args
// Destructure `names` from the props object
export default function Name({ name }) {
  return <div>My name is: {name}</div>;
}

Upvotes: 23

Related Questions