skip to Main Content

I have 2 reactjs files:

  • Reports.js (used to request report and display the result)
  • AuthContext.js (has a socket connection to maintain communication with the backend server)

user first goes to the report page generated by Reports.js and then there is a call to the backend server which returns right away but it shows a loading spinner. When the report is completed, it will send the data to AuthContext.js. However, I have trouble from AuthContext.js to be able to request a call setReportLoading() in Reports.js for the purpose of stopping the loading spinner. can you please advise how to solve this ?

I tried the method below setReportLoading() but it has this error:

setReportLoading.js:115 Uncaught TypeError: setReportLoading is not a function

here is my code snippet

In file AuthContext.js
import { setReportLoading } from 'Reports';

export const AuthProvider = ({ children }) => {

            socket.on('processmessage', (msg) => {
              if (msg.type == 'checking'){
                  setReportLoading(2);         
              }            
            }); 
   
}

In file Reports.js

const Reports = () => {

    const [loading, setLoading] = useState(1)

    const setReportLoading = (isLoading) => {
        setLoading(isLoading);
      };

      const renderContent = () => {

        if (loading === 1) return (
            <div className="d-flex justify-content-center align-items-center" style={{ minHeight: '200px' }}>
                <div className="spinner-border text-primary" role="status">
                    <span className="visually-hidden">{t('loc_react_loading')}</span>
                </div>
            </div>
        )


        if (loading === 2) return (
            <div className="mb-4 card border-0 shadow-sm" style={{'min-width': '900px'}}>
                {renderReportSelection()}
                {showReport && renderReport()}
            </div>   
        )
    }


    return (
        <DashboardLayout>
        </DashboardLayout>
    )
}

export default Reports;

UPDATE tried using jotai 2.0.0 but somehow no crash, but it didnt seem to go to handleReportloadingChange() function

in AuthContext.js

import { atom, useAtom } from 'jotai';

export const reportloadingAtom = atom(1);

export const AuthProvider = ({ children }) => {
  const [reportloading, setReportloading] = useAtom(reportloadingAtom);

  socket.on('processmessage', (msg) => {
    if (msg.type == 'checking') {
      setReportloading(2);
    }
  });

  // ...
};

in Reports.js

import { useAtom } from 'jotai';
import { reportloadingAtom } from 'AuthContext'

const Reports = () => {
  const [reportloading, setReportloading] = useAtom(reportloadingAtom);
  const [loading, setLoading] = useState(1);

  useEffect(() => {
    // This function will run every time the value of reportloadingAtom changes
    function handleReportloadingChange() {
      console.log("handleReportloadingChange")
      setLoading(reportloading);
    }

  }, [reportloading]);

  // ...
};

2

Answers


  1. I dont think you can export or import a function declared inside a React component without a third party lib. What you can do is pass it as a props to a child component.

    Given the code you have shared, I would sugest you refactor your AuthProvider to a regular function, and not a React component. I suggest this because I dont see your AuthProvider as a child of your Reports component. You can then call this function within your Reports component and have it return some value to then change the vaue of your loading.

    Login or Signup to reply.
  2. It seems like you are trying to use Jotai to manage state between components. In your Jotai-based solution, you’ve created an atom reportloadingAtom to manage the loading state and attempted to use it in both AuthContext.js and Reports.js. However, there are some issues in your implementation.

    AuthContext.js

    import { atom, useAtom } from 'jotai';
    
    export const reportloadingAtom = atom(1);
    
    export const AuthProvider = ({ children }) => {
      const [reportloading, setReportloading] = useAtom(reportloadingAtom);
    
      socket.on('processmessage', (msg) => {
        if (msg.type === 'checking') {
          setReportloading(2);
        }
      });
    
      // ...
    };
    

    Reports.js

    import { useAtom } from 'jotai';
    import { reportloadingAtom } from 'AuthContext';
    
    const Reports = () => {
      const [reportloading, setReportloading] = useAtom(reportloadingAtom);
      const [loading, setLoading] = useState(1);
    
      useEffect(() => {
        // This function will run every time the value of reportloadingAtom changes
        setLoading(reportloading);
      }, [reportloading]);
    
      // ...
    
      return (
        <DashboardLayout>
          {/* Render your components based on the loading state */}
        </DashboardLayout>
      );
    };
    
    export default Reports;
    

    Here are some improvements:

    1. Use === for strict equality comparison.
    2. You don’t need to manually create a handler function for atom changes in Reports.js; Jotai will handle it.

    Ensure that both components are wrapped with the JotaiProvider at the highest level of your component tree. If you haven’t done so, you can use it like this:

    import { JotaiProvider } from 'jotai';
    
    const App = () => {
      return (
        <JotaiProvider>
          {/* Your components */}
        </JotaiProvider>
      );
    };
    

    This should help in managing the loading state between your components using Jotai. If you still face issues, consider checking the console for any error messages or log statements that might provide more information about what’s going wrong.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search