3

I have an AuthService class that provides all the api calls and handles authentication for those calls, so its a nice modular service. It is not a React component and not used in any render calls. It handles fetch calls mostly. In many other classes now, I use a single global instance of this class, and import it at the top.

I don't think a context is the right approach because it's not an object type or used in renders. I use the instance in componentDidMount() and useEffect().

an example:

//at the bottom, outside curly braces defining AuthService
export const Auth = new AuthService();

a consumer:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { useState, useEffect } from 'react';
import CommentList from "./CommentList";
import CommentForm from "./CommentForm";
import Comment from "./Comment";
import AuthService from './AuthService';
import { Auth } from './AuthService';

export default function CommentBox(props) {

const [comments, setComments] = useState([]);
// const Auth = new AuthService();
const [formText, setFormText] = useState('');
const [update, setUpdate] = useState(false);

useEffect(() => {

    Auth.fetch('/comments/get_comment_for_bill/' + props.id + '/').then((data) => {
        if (typeof data[0] !== 'undefined') {
            setComments(data);
        } else {
            setComments([]);
        }
        setUpdate(false);
    });
    return () => {
        return;
    }
}, [props, update]);

return (
    <div >         
        <CommentList comments={comments}/>
        <CommentForm id={props.id} formText={formText} setFormText={setFormText} setUpdate={setUpdate}
            onChange={e => {
                setFormText(e.target.value);                  
            }} />           
    </div>

);
}
Stevie
  • 326
  • 3
  • 16

2 Answers2

2

I think the best approach to using singletons in React is by attaching it to the window object. Just make sure you first attach the singleton to an object, which in turn is attached to the window object - to avoid polluting your window namespace. You would do this attaching in your startup script only once:

index.js

var window.app = {}
window.app.authentication = (function() {
   function authenticateUser(userId) {

   }

   return {
      authenticateUser: authenticateUser
   }
})();

Then in some other module where you want to use it:

Login.js

window.app.authentication.authenticateUser("johndoe");
Johann
  • 27,536
  • 39
  • 165
  • 279
  • But... why pollute the global context? I like OP's original idea -- export a `const` instantiation and import iff you need it. What's the advantage here? – ruffin Jul 24 '23 at 14:52
-2

It's just fine. There's nothing wrong. But why use same instance for everything?

new AuthService()

I would recommend you to export AuthService. Then, whenever you'll need to use that service, define a new instance and use:

const Auth = new AuthService()
// now, use Auth

It's just a personal choice.

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
  • 1
    is there any downside to having like a dozen instances of AuthService? I thought it was more efficient to use a single one? – Stevie Apr 28 '19 at 19:29
  • There may be downside with single one. Just think of interruption of multiple service call to the same instance. One application block will hold all call. Which I think is not good idea. – Bhojendra Rauniyar Apr 28 '19 at 19:37
  • 4
    There's a reason why singleton's exist. Telling someone to just make copies of a class when they requested help to make a singleton is ridiculous. – Johann Mar 06 '20 at 11:22