[SOLVED] Button Function Not calling From Another file in React

Issue

I need to call CutomerDashboard.js file’s "toggleIsTrucated" function and "isTruncated" to CustomerNotice.js files button onClick and text change places, How can I call that?

(In this customer dashboard file I’m creating a Read function to show some extent of notice text)

    import React, {useState,useEffect} from 'react';
    import { Input, Row, Col, Button } from 'antd';
    import {fetchDashboardMetrics} from "./DashboardApi";
    import {items} from "./DashboardItems";
    import axios from 'axios';
    import CustomerNotice from "./CustomerNotice";
    
    function Read ({children}) {
    
        const text = children;
    
        const [isTruncated, setIsTrucated] = useState(true); 
    
        const result = isTruncated ? text.slice(0,90) : text;
    
        function toggleIsTrucated(){
            setIsTrucated(!isTruncated);
         }
    
        return (
            <div>
                {result}....
            </div>
            
        );
    
    }
    
    
    const CustomerDashboard = () => {
    
        const [features, setFeatures] = useState(items);
        const source = axios.CancelToken.source()
        const [notice, setNotice] = useState(<Read>Customer Notice: Optimism Is Invaluable For The Meaningful Life. With A Firm Belief In A Positive Future You Can Throw Yourself Into The Service Of That Which Is Larger Than You Are.  -Martin Seligman-</Read>);
        const [noticeVisibility, setNoticeVisibility] = useState(true);
        
        useEffect(() => {
            fetchDashboardMetrics(features, setFeatures,source.token)
            return (() => {
                source.cancel();
            })
        }, []);
    
        return (
            <>
                <div className='md:pl-8 sm:pl-0'>
                    <div className='my-5 '>
                        <p className='mb-8'>My Account - Dashboard Overview</p>
                        {noticeVisibility && <CustomerNotice notice={notice} setNoticeVisibility={setNoticeVisibility}/>}
                    </div>
                    <ul role="list" className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
                        {features.map((feature) => (
                            <li key={feature.name} className="col-span-1 bg-white rounded-lg shadow divide-y divide-gray-200 relative">
                                <div className="w-full flex items-center justify-between p-6 space-x-6">
                                    <div className="flex-1 truncate">
                                        <div className="flex items-center space-x-3 justify-between">
                                            <h3 className="text-gray-900 text-lg truncate">{feature.name}</h3>
                                            {feature.isNew && (
                                                <div className="absolute -top-2 -right-2 p-1 px-4 text-white text-sm bg-red-500">
                                                    New
                                                </div>
                                            )}
                                        </div>
                                    </div>
                                </div>
                                <div>
                                    <div className={'mx-4 mt-2 mb-3 '}>
                                        {feature.details.map((singleDetail) => {
                                            return (
                                                <div className={'flex justify-between text-base'}>
                                                    <span>{singleDetail.name}</span>
                                                    <span>{singleDetail.value}</span>
                                                </div>
                                            )
                                        })}
                                    </div>
                                </div>
                            </li>
                        ))}
                    </ul>
                </div>
            </>
        )
    }
    export default CustomerDashboard;



    import React, {useState,useEffect} from 'react';
    import {XIcon} from "@heroicons/react/solid";
    
    const CustomerNotice = ({notice, setNoticeVisibility}) => {
        return (
            <div>
                <div className="mt-8 pb-2 sm:pb-5">
                    <div className="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
                        <div className="p-2 rounded-lg bg-orange-600 shadow-lg sm:p-3">
                            <div className="flex items-center justify-between flex-wrap">
                                <div className="w-0 flex-1 flex items-center">
                                    <p className="ml-3 font-medium text-white truncate">
                                        <span className="md:inline">{notice}</span>
                                    </p>
                                </div>
                                <div className="order-3 mt-2 flex-shrink-0 w-full sm:order-2 sm:mt-0 sm:w-auto">
                                    <a
                                        href="#"
                                    className="flex items-center justify-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-orange-600 bg-white hover:bg-orange-50"
                                    >
                                        <button onClick={toggleIsTrucated}>{isTruncated ? "Read More" : "Read Less"}</button>
                                    </a>
                                </div>
                                <div className="order-2 flex-shrink-0 sm:order-3 sm:ml-2">
                                    <button
                                        onClick={() => setNoticeVisibility(false)}
                                        type="button"
                                        className="-mr-1 flex p-2 rounded-md hover:bg-orange-500 focus:outline-none focus:ring-2 focus:ring-white"
                                    >
                                        <span className="sr-only">Dismiss</span>
                                        <XIcon className="h-6 w-6 text-white" aria-hidden="true"/>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    };
    
    export default CustomerNotice;

If this is not possible please suggest me a possible way.

Solution

Instead of doing a bunch of hacks, I would recommend simplifying the structure of your components.

import { useState } from 'react'

export default function CustomerDashboard() {
  // I am not sure why you want to keep notice in state,
  // because in your example you did not call setNotice
  const [notice, setNotice] = useState(`
    Customer Notice: Optimism Is Invaluable For The Meaningful Life.
    With A Firm Belief In A Positive Future You Can Throw Yourself Into The Service
    Of That Which Is Larger Than You Are. -Martin Seligman
  `)
  const [isNoticeVisible, setIsNoticeVisible] = useState(true)

  return (
    <div>
      <h1>My Account - Dashboard Overview</h1>

      {isNoticeVisible && (
        <CustomerNotice
          notice={notice}
          setIsNoticeVisible={setIsNoticeVisible}
        />
      )}
    </div>
  )
}

function CustomerNotice(props) {
  const { notice, setIsNoticeVisible } = props
  const [isTruncated, setIsTruncated] = useState(true)

  function toggleIsTruncated() {
    setIsTruncated(!isTruncated)
  }

  return (
    <div>
      <Read text={notice} isTruncated={isTruncated} />

      <button onClick={toggleIsTruncated}>
        {isTruncated ? 'Read More' : 'Read Less'}
      </button>

      <button onClick={() => setIsNoticeVisible(false)}>Dismiss</button>
    </div>
  )
}

function Read(props) {
  const { text, isTruncated } = props
  const result = isTruncated ? text.slice(0, 90) : text

  return <div>{result}....</div>
}

List of the things that were bad in your code.

  1. Keeping the component instance in the state. It is hard to manage. Even your simple case proves that.
  2. Keeping the toggleIsTruncated function inside the Read component. I think we should keep it outside and pass only 2 props to the Read component. I enable exposed only two things
const { text, isTruncated } = props

As you can see it is easy to maintain and allow us to do whatever we want.

PS. If my review and example were helpful please leave the thumbs up.

Answered By – Krystian Sztadhaus

Answer Checked By – Katrina (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *