Home > Mobile >  How to update a React component with another components Onclick event?
How to update a React component with another components Onclick event?

Time:01-06

I currently have 2 components called "Widgets" and "Tablelist". I am trying to create and pass an onClick event handler to my Widgets component to change the data within Tablelist depending on which Widget is clicked.

here is my code as of so far:

import { useState } from "react";
import { tableData, data2 } from "../../components/widgets/data";

const Home = () => {
    const [activeTable, setActiveTable] = useState("firstTable");

    const tableToggle = () => {
        setActiveTable("secondTable");
    }
    return (
        <div className="home">
            <Sidebar />
            <div className="home-container">
                <Navbar />
                    <div className="widgets">
                        <Widgets type="assets" onClick={tableToggle}/>
                        <Widgets type="liabilities"/>
                        <Widgets type="fund bal/net positions"/>
                        <Widgets type="revenue"/>
                        <Widgets type="expenses"/>
                    </div>
                    <div className="data-visual">
                        <div className="list-container">
                            <div className="list-title">Balance Sheet</div>
                            {activeTable === "firstTable" && <Tablelist title={tableData}/>}
                            {activeTable === "secondTable" && <Tablelist title={data2} />}
                        </div>
                        <div className="data-container">
                            <Donut />
                        </div>
                    </div>
            </div>
        </div>
    )
}

export default Home;

code within Widgets:

const Widgets = ({type}) => {
    let data;
    switch (type) {
        case "assets":
            data = {
                title: "ASSETS",
                amount: "17,336,942",
                isMoney: false,
                link: "See all",
            };
            break;
            case "liabilities":
            data = {
                title: "LIABILITIES",
                amount: "867,109",
                isMoney: false,
                link: "see all",
            };
            break;
            case "fund bal/net positions":
            data = {
                title: "FUND BAL/NET POSITION",
                amount: "35,279,811",
                isMoney: false,
                link: "See all",
            };
            break;
            case "revenue":
            data = {
                title: "REVENUE",
                amount: "22,474,202",
                isMoney: false,
                link: "See all",
            };
            break;
            case "expenses":
            data = {
                title: "EXPENSES",
                amount: "40,582,128",
                isMoney: false,
                link: "See all",
            };
            break;
        default:
            break;
    }

    return (
        <div className="widget">
            <div className="left">
                <span className="title">{data.title}</span>
                <span className="counter">${data.amount}</span>
                <span className="link">{data.link}</span>
            </div>
            <div className="right">
                <div className="percentage">
                    <ArrowDropUpOutlinedIcon />
                    50%
                </div>
            </div>
        </div>
    )
}

export default Widgets;
code within Tablelist:

const Tablelist = ({title}) => {

    return (
        <TableContainer component={Paper} className="table">
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell className="tablecell">Assets</TableCell>
            <TableCell className="tablecell">Balance</TableCell>
            <TableCell className="tablecell">Prior YTD</TableCell>
            <TableCell className="tablecell">Year To Year $ CHG</TableCell>
            <TableCell className="tablecell">CY Opening Balance</TableCell>
            <TableCell className="tablecell">TYD $ Change</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {title.map((row) => (
            <TableRow
              key={row.assets}>
              <TableCell className="tablecell">{row.assets}</TableCell>
              <TableCell className="tablecell">{row.balance}</TableCell>
              <TableCell className="tablecell">{row.priorYTD}</TableCell>
              <TableCell className="tablecell">{row.yearToYear}</TableCell>
              <TableCell className="tablecell">{row.cyOpeningBal}</TableCell>
              <TableCell className="tablecell">{row.ytdChange}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

export default Tablelist;

I tried creating the Onclick event inside of my Widgets component where I was able to console log the desired output but my Tablelist component doesn't seem to recognize.

const tableToggle = () => {
        if(type === "assets") {
            console.log("firstTable")
        } else if (type === "liabilities") {
            console.log("secondTable") 
        } else {
            console.log("error")
        }
    }

    return (
        <div className="widget" onClick={tableToggle}>
            <div className="left">
                <span className="title">{data.title}</span>
                <span className="counter">${data.amount}</span>
                <span className="link">{data.link}</span>
            </div>
            <div className="right">
                <div className="percentage">
                    <ArrowDropUpOutlinedIcon />
                    50%
                </div>
            </div>
        </div>

    )
    
}

CodePudding user response:

It seems like you are trying to handle a state between multiple components. To do this effectively I would recommend looking into React context, it helps you handle a piece of state between different components. With React context, you will be able to have a button click from your Widgets or Home component affect a piece of state accessible by Tablelist as well.

Here is a nice code snippet from the React doc on how to handle this with a piece of state called Dark Mode: useContext React Docs. Here, a checkbox in MyApp component can influence a theme data object (either Dark or Light) in the Panel or Button component.

CodePudding user response:

You need to use the onclick prop that you are passing to the widgets component:

<Widgets type="assets" onClick={tableToggle}/>

So this Widgets component should do the trick:

const Widgets = ({type, onClick}) => {
    let data;
    switch (type) {
        case "assets":
            data = {
                title: "ASSETS",
                amount: "17,336,942",
                isMoney: false,
                link: "See all",
            };
            break;
            case "liabilities":
            data = {
                title: "LIABILITIES",
                amount: "867,109",
                isMoney: false,
                link: "see all",
            };
            break;
            case "fund bal/net positions":
            data = {
                title: "FUND BAL/NET POSITION",
                amount: "35,279,811",
                isMoney: false,
                link: "See all",
            };
            break;
            case "revenue":
            data = {
                title: "REVENUE",
                amount: "22,474,202",
                isMoney: false,
                link: "See all",
            };
            break;
            case "expenses":
            data = {
                title: "EXPENSES",
                amount: "40,582,128",
                isMoney: false,
                link: "See all",
            };
            break;
        default:
            break;
    }

    return (
        <div className="widget" onClick={onClick}>
            <div className="left">
                <span className="title">{data.title}</span>
                <span className="counter">${data.amount}</span>
                <span className="link">{data.link}</span>
            </div>
            <div className="right">
                <div className="percentage">
                    <ArrowDropUpOutlinedIcon />
                    50%
                </div>
            </div>
        </div>
    )
}

export default Widgets;

CodePudding user response:

I Have Very Easy Solution

The customAttributes Is The Fast Solution

example

go to public/index.html and add this attribute

<body data-custom="false">
</body>

import React, {
  useEffect
} from 'react';

export default yourfunction() {
  // ...
  useEffect(() => {
    document.body.dataset.custom = !document.body.dataset.custom;
  }, [ /* the change will update */ ])
  // ...
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

In The Other Component You Will Change

import React, {useEffect} from 'react'

export default myFunction() {
  // ...
  useEffect(() => {
    // add what you want here to change
  }, [document.body.dataset.custom])
  // ...
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

  • Related