Coder Social home page Coder Social logo

flagsmith / flagsmith-js-client Goto Github PK

View Code? Open in Web Editor NEW
60.0 14.0 34.0 10.09 MB

Javascript Client for Flagsmith. Ship features with confidence using feature flags and remote config. Host yourself or use our hosted version at https://www.flagsmith.com/

Home Page: https://www.flagsmith.com/

License: BSD 3-Clause "New" or "Revised" License

JavaScript 14.02% TypeScript 85.98%
feature-flags feature-flag feature-flagging feature-flaggers remote-config ci cd continous-integration continuous-delivery continuous-deployment feature-toggles feature-toggle react-native javascript

flagsmith-js-client's Introduction

Flagsmith Javascript Client

npm version

The SDK clients for web and React Native for https://www.flagsmith.com/. Flagsmith allows you to manage feature flags and remote config across multiple projects, environments and organisations.

Adding to your project

For full documentation visit https://docs.flagsmith.com/clients/javascript/

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Getting Help

If you encounter a bug or feature request we would like to hear about it. Before you submit an issue please search existing issues in order to prevent duplicates.

Get in touch

If you have any questions about our projects you can email [email protected].

Useful links

Website

Documentation

flagsmith-js-client's People

Contributors

adrianso avatar azriel46d avatar benrometsch avatar dabeeeenster avatar danielantunesfernandes avatar dependabot[bot] avatar eschaefer avatar gf3 avatar kyle-ssg avatar levrik avatar lnikell avatar lukefanning avatar matthewelwell avatar msimulcik avatar niledaley avatar nitz14 avatar nogoodusername avatar novakzaballa avatar prettywood avatar rstuven avatar rustmn avatar sahanatroam avatar td-4242 avatar tsyirvo avatar ukabu avatar xrash avatar zxl634 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flagsmith-js-client's Issues

Ampersand in name of User causing bullet-train to malfunction system-wide for that user

Hello,

I'd like to report an issue that we've come across about a month ago (sorry for procrastinating on reporting this).

In our bullet-train configuration, we added a User named 369___H&R_Block

Few days later they reported our app malfunctioning in a few different places.

We realized that the & in the user name was causing an issue during the .identify function of the package.

This caused the rest of our data received from our API to be broken as well.

Here's what we did to resolve it for the time being:

bulletTrain.identify('...some user name here...'.replace(/&/g, '_AND_'));

But we thought you guys would like to know about it.

By the way, big fans of bullet-train.
Really great to use. Thank you

Roee, Webiya

CORS error

Hello,

I am getting this CORS issue, not happen to all users, just to some my users.

'https://api.bullet-train.io/api/v1/traits/' from origin 'https://mywebsite.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Could anyone has experienced on this, or how to configure the request header to pass to bullet to overcome this CORS issue?

Thanks/Cuong

Flagsmith Examples

This issue is to keep track of working examples in different frameworks or patterns. Add any requests or reference any PRs in this thread.

  • Vanilla Javascript
  • JQuery
  • Angular Modern
  • Deno
  • React
  • Next.js with SSR

api is undefined when setTrait or setTraits is called before init

When trying to call setTrait or setTraits before init then api is undefined because the default value is only set during init.

 init({
  environmentID,
  api = defaultAPI,
  onChange,
  ...
setTrait = (key, trait_value) => {
  const { getJSON, identity, api } = this; <-- api is undefined before init
  ...

I don't think setTrait and setTraits is supposed to call the bullettrain api if it has not been initialized, instead only set the traits in state.

Undocumented error: "Exception fetching evaluationEvent ReferenceError: state is not defined"

Hey there, it's me again!

I'm testing your JS client in one of our Angular (v11) apps. For testing purposes, I've initialized the client with logging turned on.

I get the following error logged into the console repeatedly:

FLAGSMITH: 40194 ms Exception fetching evaluationEvent ReferenceError: state is not defined

I can see that this error message is printed here in your source.

My first priority is to understand whether this has any functional implications. I've checked the network tab of my developer tools report to see what's happening with that request.

Roughly at the same with this error, I see POST request to /analytics/flags returns a 200. It has the expected request payload (as far as I can tell). The response body is empty. So it seems to be fine, I guess?

I've figured I'd turn off analytics to see if that'd help. I seem to be getting this error regardless of the enableAnalytics parameter of the init() method. Is that parameter not respected?

I'm happy to provide more details from my side if you need that.

React 18 support?

There are a few changes needed for flagsmith to work with react v18. Is there any timeline for these changes?

Add changelog or releases?

Hey! I think it would be useful to provide a changelog or a release list on Github so it's easy to see what has changed since the last version. I have just opened this issue and the way I caught that was by first looking at the version difference which had no release info, then I went into our build logs to see what crashed, and finally to the Flagsmith source code to find the offending code. Beyond the obvious benefits of change history, it changelog could be useful to faster pinpoint any potential breaking changes in the future

Undocumented behavior on functions identify and logout

The documentation for function identify says:

Identify as a user, optionally with traits e.g. {foo:"bar",numericProp:1,boolProp:true}. This will create a user for your environment in the dashboard if they don't exist, it will also trigger a call to getFlags(), resolves a promise when the flags are updated.

The documentation for function logout says:

Stop identifying as a user, this will trigger a call to getFlags()

As you can see, the documentation explicitly states that these functions will trigger a call to getFlags() and doesn't mention any exceptional case - but there is one exceptional case: if a listener has been set up by means of flagsmith.startListening, then neither identify or logout will call getFlags.

It looks like this exceptional case should be mentioned in the docs, or removed from the code, or addressed somehow.

This PR #104 proposes a fix.

React: Unhandled Rejection (TypeError): PromiseReject called on non-object

When initializing the client in a react project I'm unable to gracefully catch/handle the error if a connection the the API endpoint fails.

To reproduce this error using your example script, try adding the api parameter to init, using some unresponsive URL. ie:

componentWillMount() {
     const { handleFlags, handleFlagsError } = this;
     flagsmith.init({
       api: 'http://notavalidurl.com',
       environmentID,
       ...
    });
...

The unhnadled rejection bubbles to the top and I can't seem to catch it. I've tried adding the onError callback handler to init, as well as adding a .catch() after the init call, but nothing wants to catch this exception.

Feature: add setTraits, allow it to be called before init

Hi

As the subject says, setTrait can not be called before init() as it says in the documentation.

If you do it, you will do requests to undefinedtraits/.

setTraits depends on api that is set during the initialization:

setTrait = (key, trait_value) => {
    const { getJSON, identity, api } = this;

    const body = {
        "identity": {
            "identifier": identity
        },
        "trait_key": key,
        "trait_value": trait_value
    }

    return getJSON(`${api}traits/`, 'POST', JSON.stringify(body))
        .then(this.getFlags)
};

Possible inconsistency in IBulletTrainFeature and getValue() declarations

Hi,

I'm a bit puzzled by the following (type) declarations.

declare class IFlagsmith {
    ...
    /**
     * Returns the current flags
     */
    getAllFlags:()=> IFlags

    /**
     * Get the value of a particular remote config e.g. flagsmith.getValue("font_size")
     */
    getValue:(key: string) => string|number|boolean
    ...

If I understand it correctly:

  • getAllFlags() will return the flags
  • (Given that there's a flag among them with key buttonSize and value 1) getValue(buttonColor) will return 1.
  • According to the type declaration, this is expected.

Notice the inline documentation of getValue() is inconsistent in its terminology choice with the description here: "remote config" and "feature".


I believe IBulletTrainFeature is supposed to represent flags that we receive from you, see onChange() and getAllFlags().

Relevant type declarations are:

export interface IFlags {
    [key: string]: IBulletTrainFeature
}

and

export interface IBulletTrainFeature {
    enabled: boolean
    value?: string
}

If this all makes sense... getValue() and IBulletTrainFeature.value should be referring to the same entity. If I got that correct, I don't see how they can have different types.

And indeed... if I set a feature flag like below, it comes back as a number rather than a string:
image

Client does not return flags - self hosted api server

I initialized the client with :

bulletTrain.init({
        api,
        environmentID,
        onChange: handleFlags,
        onError: handleErrors,
        defaultFlags
      })
// api="https://bullet-train-api-experiment...com/api/v1/"
// environmentID="m...G"
// defaultFlags={
//    hello_world: true
// }
  handleFlags = (flags, params) => {
    this.setState({ flags })
    console.log(flags, params, bulletTrain.getAllFlags())
  }

In the console (from the handleFlag listener) I get : {}, {isFromServer: true}, {}

The response I get from the API server is :

[{"id":2,"feature":{"id":1,"name":"hello_world","created_date":"2018-12-11T20:55:38.891097Z","initial_value":null,"description":null,"default_enabled":false,"type":"FLAG","project":1},"feature_state_value":null,"enabled":true,"environment":2,"identity":null}]

if I call bulletTrain.hasFeature("hello_world") I always get false.

Need option to handle flagsmith init with invalid or bad token

while going through and validating some operational scenarios in our application I've found that I can't pass an invalid token to flagsmith.init and have a way to gracefully recover.

image

for example:

flagsmith.init({
  api: flagsmith_url,
  environmentID: 'BAD_TOKEN'
  defaultFlags,
  onChange,
})

I would expect this to initialize flagsmith with the contents of defaultFlags and be disconnected from the api server.

Also within this testing I checked having api: 'http://badurl' at which point flagsmith would load defaultFlags and continue.

Unsafe use of global flagsmith instance in Next.js example

Hi there,

I've followed the example use of Flagsmith SDK in the Next.js application and I think the global instance of the SDK should not be used.

Suppose you have the following code in your _app.tsx:

import flagsmith from 'flagsmith-es/isomorphic';

MyApp.getInitialProps = async ({ ctx }) => {
    await flagsmith.init({
        environmentID,
        identity: getIdentityFromCookies(ctx),
    });
    await new Promise((resolve) => { // simulate another asynchronous code
        setTimeout(resolve, 5000);
    });
    return {
        flagsmithState: flagsmith.getState(),
    };
};

Because the flagsmith instance is global and thus shared across all requests, one request can rewrite the data of another request. Consider the following scenario:

  1. Incoming request A.
  2. getIntitialProps of _app.tsx is executed.
  3. Global flagsmith instance is initialized for request A.
  4. Another asynchronous code inside getIntialProps is being executed.
  5. Incoming request B.
  6. getIntitialProps of _app.tsx is executed.
  7. Global flagsmith instance is initialized for request B with a different identity (rewriting identity of request A).
  8. Asynchronous code inside getIntialProps for request A gets finished.
  9. Page for request A with incorrect feature flags and identity gets rendered and sent to the client.
  10. Page for request B gets rendered and sent to the client.

I've successfully replicated this scenario locally, I can provide you working example if you want.

This may seem like a rare race condition, however, in applications with higher load (eg. 100+ requests per minute for one Node.js process) the likeliness of this could get quite high.

I suggest creation of a new instance of the SDK for each invocation of getInitialProps inside _app.tsx using createFlagsmithInstance and storing it into Next.js's context (ctx), which is designated for this purpose.

Please let me know if I've missed something or if this is a potential issue.

Thank you for a great piece of open-source software with really good documentation!

Trait names converted to lower case on retrieval

Hi there,

it seems the client converts all trait names to lower case. On the server trait names are dispayed correctly (case sensitive).

Expected Behavior

bulletTrain.setTrait('camelCase', 'foo')
bulletTrain.getTrait('camelCase') => 'foo'
bulletTrain.getTrait('camelcase') => undefined

Observed Behavior

bulletTrain.setTrait('camelCase', 'foo')
bulletTrain.getTrait('camelCase') => undefined
bulletTrain.getTrait('camelcase') => 'foo'

THanks and best regards,
Michael

Feature: Allow loading flags in React SSR

Is there anyway I can use the JS client in React App that uses Server Side Rendering?

Right now, the seems the client requires a window object to work. Which prevent it from being used in an app that uses SSR (our apps uses Next.js).

SyntaxError when importing in browser via ES6 modules

We're using ES6 modules to build an application. The application JavaScript is complied with Rollup and imported as a ES6 module. For example (where index.js is our application code):

<body>
  <script type="module" src="index.js"></script>
</body>

Our application (which is compiled to index.js in the example above) imports the Flagsmith JavaScript SDK via NPM (shortened for clarity):

import flagsmith from 'flagsmith';

flagsmith.init();

This approach looks fine in the IDE, but in the browser throws an error:

Uncaught SyntaxError: The requested module './../node_modules/flagsmith/index.js' does not provide an export named 'default'

Using this approach, it also appears that window.flagsmith is defined. We're using ES6 modules to avoid "polluting" the global window object, so this is undesired behavior.

The use case is developing a JS SDK ourselves, and want to use our own instance of Flagsmith to control functionality. That SDK is used inside of third-party sites so we can't set anything on the window object.

init() to gurantee Flagsmith won't be reinitialized more than once?

already asked on SO but didn't get a reply. so sorry for spamming it here. Basically, we want to create a wrapper for FS since our need differs:

import flagsmith from 'react-native-flagsmith';

flagsmith.init({
environmentID: Config.FLAGSMITH_ENVIRONMENT_ID,
api: Config.FLAGSMITH_API_URL,
asyncStorage: AsyncStorage,
cacheFlags: true,
onError: handleFlagsError,
onChange: (oldFlags, params) => {},
defaultFlags: TabletConfigurations
});

function getValue(key){
const value = flagsmith.getValue(key);
//logic that works based on value and key goes here
return someresultnow;
}


const FS = {getValue};

export default FS;

all is good so far but I was wondering why I can't wrap the initalization in a function because I want to manually. Sure, I can do the init() in the component but I want to keep all flagsmith related tasks in the file. So, I tried the following but it returns two errors randomly:

async function initFS(){
try{
   await flagsmith.init({...});
  //began listening
}catch(e){
console.log(e)
}
}

// from entry of the app:

await iniitFS()

one of the errors is 'u.getItem' (u is undefined) and another one flags is undefined. Why does it not initialize when I wrapped it in a function but does get initalized outside of the function?

Error: Uncaught (in promise)

Hello,

I'm currently evaluating different feature toggle services and stumbled upon an error while implementing bullet-train into our angular app. I also checked out the example in this repo and got the same error.

Steps to reproduce

  1. Open dev console while running the angular app
  2. change the env/ironmentID in app.component.ts:12: https://github.com/SolidStateGroup/bullet-train-js-client/blob/006526e1d2df56be53790967858aa0a2c4a1c899/examples/angular/src/app/app.component.ts#L12
    to something none existing (e.g. '1234') to force the backend to respond with a 403.
  3. reload the app

Actual behavior

core.js:6014 ERROR Error: Uncaught (in promise): (intermediate value)(intermediate value).forEach is not a function
    at resolvePromise (zone-evergreen.js:797)
    at zone-evergreen.js:707
    at index.js:1
    at ZoneDelegate.invoke (zone-evergreen.js:359)
    at Object.onInvoke (core.js:39699)
    at ZoneDelegate.invoke (zone-evergreen.js:358)
    at Zone.run (zone-evergreen.js:124)
    at zone-evergreen.js:855
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39680)

onError is called, but the error message we get in onError: (error) => {} is actually {message: "(intermediate value)(intermediate value).forEach is not a function"}

Expected behavior

no error message shown in console and onError being called with the correct error of the api response {detail: "Invalid or missing Environment Key"}.

Typescript type definition file does not have a default export.

It is not possible to import the flagsmith module from the npm package in Angular 11, which compiles to ES6 due to a missing default export.

import flagsmith from 'flagsmith';

will cause following error:
Module '"flagsmith"' has no default export.

Anyway, your index.d.ts does not really reflect you javascript code base. In reality you have a default export a constant of a class which you also should mirror in the index.d.ts

flagsmith.init({...}) call resulting in a 404 when attempting to retrieve flags

I first noticed this issue mid-June, but was unable to find any solution for it.

I have not made any changes to my project and it was working before, so I can only guess that something with your API changed.

Screen Shot 2022-07-05 at 10 19 58 PM

The following code produces the error message: Failure! string 0

flagsmith.init
({
    environmentID:"[enter your own environmentID]",
    onChange: (oldFlags, params) =>
    {
        console.log("Success!");
    },
    onError: (errors) =>
    {
        console.log("Failure!", typeof(errors), errors.length, errors);
    }
});

Anyone here have any ideas on what might be causing this strange issue?

(Partially?) incorrect type annotation for onError callback

Here I read that the callback will be passed an argument of type:

{
  message: string
}

I've tested this by passing an incorrect API key to init() and it led to a runtime exception.

Looking at the network response, the type annotation seems incorrect as your API returns:

{
  detail: string
}

Add an option to add user identification in FlagsmithProvider

I tried migrating to the new flagsmith/react using hooks and the FlagSmithProvider.

However I am now running into frustrating race conditions on the identify...

Without the Provider/hooks I am able to identify my user as soon as they pass the Authentication step in my app (before React renders) and the first call to flagsmith ends up having the correct user identified flags

However with the new useFlagsmith hook that's suggested to identify a user with. This can only happen after React has rendered, and in a component at a lower level than the FlagsmithProvider.

That means now on the first render of my app and the first fetch of flagsmith flags, I get default values. Then when useEffect runs (which I had to put in a random nonsensical place due to the structure here) it fetches flags again with the right attributes.

This is a waste and frustrating to deal with.

Please let me identify the user via props in the FlagsmithProvider instead of the useFlagsmith hook. It will clean up my app and fix the race condition issue.

Version 2.0.10 contains breaking change

Hey! Just got notified by the dependency bot there's an upgrade available from 2.0.9 to 2.0.10. Running tests on that fails with the following error:

Failed to compile.
TS2345: Argument of type '{ environmentID: string; onChange: () => void; }' is not assignable to parameter of type 'IInitConfig'.
  Property 'angularHttpClient' is missing in type '{ environmentID: string; onChange: () => void; }' but required in type 'IInitConfig'.
 66 |     }
 67 |
> 68 |     flagsmith.init({
    |^
> 69 |       environmentID,
    |^^^^^^^^^^^^^^^^^^^^
> 70 |       onChange: () => {
    |^^^^^^^^^^^^^^^^^^^^
> 71 |         onDone();
    |^^^^^^^^^^^^^^^^^^^^
> 72 |       },
    |^^^^^^^^^^^^^^^^^^^^
> 73 |     });
    |^^^^^^
 74 |   }, [init, setFeatureFlags]);
 75 |
 76 |   useEffect(() => {
error Command failed with exit code 1.

As you can see, Flagsmith expects the property angularHttpClient to exist. However, I am not even in Angular project, so this shouldn't be an issue.

Dynamic Code Evaluation prevents Flagsmith to run on Next.js middlewares

Hi,

I'm trying to run flagsmith on a Next.js middleware to load different routes depending on flags as below:

import flagsmith from "flagsmith/isomorphic";
import { NextRequest, NextResponse } from "next/server";

flagsmith.init({
  environmentID: {{ENVIRONMENT_KEY}},
});

export default async function middleware(request: NextRequest) {
  const url = request.nextUrl.clone();

  if (flagsmith.hasFeature(url.pathname)) {
    const UUID = crypto.randomUUID();

    await flagsmith.identify(UUID);
    url.pathname = flagsmith.getValue(url.pathname) as string;

    const response = NextResponse.rewrite(url);

    return response;
  }
}

It runs locally, but fails on build with the error:

./node_modules/flagsmith/index.js
Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Middleware pages/_middleware

Import trace for requested module:
./pages/_middleware.ts

I would like to know if there is a plan to support Next.js Middlewares in the near future.

For reference:

Edge Runtime Unsupported APIs


UPDATE

The Function calls are added when AsyncStorage is used. If you don't pass it as a parameter and build the project, it will not include any dynamic code evaluation on the index files.

// index.ts - line 6
const flagsmith = core({ fetch });

This is not a solution, just some progress on the investigation.

getFlags() , identify(), setTrait(), setTraits() Promise doesn't return a value when resolved. Returns undefined

flagsmith.getFlags()
.then((res) => console.log(res))
.catch((err) => console.log(err));

This prints out as undefined
The exact same thing is happening with all the functions which internally calls getFlags() like identify(), setTrait(), setTraits().

I can see the API call in the network tab and it is successful with the proper flags returned. But the value doesn't resolve in the promise returned by any of the functions.

I am first calling flagsmith.init() and then flagsmith.identify()

TS type broken for React Native

In this commit: a7ef16a

You can see the TS declaration was changed from react-native-flagsmith to just flagsmith. Now import flagsmith from 'react-native-flagsmith' fails to pick up the types.

Polling restart and interval changing issue

Hi there,

I just started using bullet train with a self-hosted server and so far it's a great, smooth and fun to use tool :-)

However, I stumbled across two issues with updating/restarting polling intervals (client version 0.2.5).

Expected behavior:

  1. Repeated calls to startListening() update the poll interval
  2. After calling stopListening(), a call to startListening() will restart polling

Observed behavior:

  1. The update interval from the initial call continues to apply
  2. After calling stopListener(), polling will not resume on startListening()

How to reproduce:

Note: Uncomment if clause for case 2.

    onChange: (oldFlags, params) => {
      var interval = bulletTrain.getValue('feature_flags_update_interval') || 60000
      if (interval !== currentListeningInterval) {
        // if (oldListeningInterval > 0) {
        //   bulletTrain.stopListening()
        // }
        if (interval > 0) {
          bulletTrain.startListening(interval)
        }
        currentListeningInterval = interval
      }
    }

Is there anything I'm doing wrong here or is this a bug?

Thanks and best regards,
Michael

Feature request: Prevent side effects on `bulletTrain.init`

We use this library in a react native app and wrap the onChange callback in an event channel using redux saga. Since we only subscribe to channel updates after initialization it would be great if there was an option to prevent API calls during bulletTrain initialization (as to not waste our paid API calls).

Currently we use a workaround setting disableCache: true as this will stop getFlags from being called on init, but this feels like sort of a hack.

Having an explicit way to call bulletTrain.init without side effects would be great! 🙏🏼

onError not firing when no envrionment id is specified

Perhaps I am wrong but I was under the impression that when there is an error initalizing flagsmith, the onError call back is called. Here is my step, which on purpose doesn't have envrionment Id.

handleFlagsError has logic depending on the envrionment that I want to confirm with a unit test. The following is the code:

const handleFlagsError = (e) => {
  console.log('reached error handler');
};

const initializeFlagSmith = () => {
   flagsmith.init({
    environmentID: Config.FS_ENVID,
    api: 'url',
    asyncStorage: AsyncStorage,
    cacheFlags: true,
    onError: handleFlagsError,
    defaultFlags: TabletConfigurations
  });
  flagsmith.startListening(30000);
};

now I understand envrionment ID is required but i am not seeing logs in my console. Now in my test I am doing:

Config.FS_ENVID = undefined;
initializeFlagSmith();

I don't see console from handleFlagsError but I do see Please specify a environment id which is thrown out I believe by flagsmith itself. I was hoping to see simply:

'reached error handler'

hope I made sense.

bulletTrain.segment is throwing an error.

I'm using React v16.12.0

When I use bulletTrain.segment, I get the error below:
bullet_train_client__WEBPACK_IMPORTED_MODULE_1___default.a.segment

Full Code


const environmentID='dfsssffsdsfsfsdsdsggdsfs';

export const useBulletTrain = () => {
  const [hasLoaded, setHasLoaded] = useState(false);
  const [enableTimeAttendance, setEnableTimeAttendance] = useState(false);
  const [belongsToTrailUsers, setBelongToTrialUsers] = useState(false);
  
  useEffect(() => {

    bulletTrain.identify('yhjgjgjhgjgjgjg');
    bulletTrain.init({
      environmentID,
      defaultFlags: {
        enable_time_attendance: false
      },
      onChange: () => {
        try {
          bulletTrain.segment("trial_users");
        } catch (error) {
          console.log({error}) // error caught here 
        }

        setHasLoaded(true);
        setEnableTimeAttendance(bulletTrain.hasFeature("enable_time_attendance"));
        setBelongToTrialUsers(bulletTrain.segment("trial_users"));
      }
    });
  }, []);

  return { hasLoaded, enableTimeAttendance, belongsToTrailUsers };
};

non-standard import of EventJS

Hello. My company is considering using Flagsmith. When I was reviewing the source code I found a few issues. (1) there are lots of ts-ignore comments which is worrysome. (2) There is a copy and paste of EventJS in there.

function Eventjs(){"use strict";var e={};var r=this;for(var t=0;t<arguments.length;t++){var n=arguments[t];switch(typeof n){case"string":e[n]=[];break;case"object":r=n;break;default:throw new TypeError("Eventjs() only accepts string and object parameters");break}}if(r===this&&!(this instanceof Eventjs)){throw new ReferenceError('Eventjs is not called with "new" keyword and no parameter of type object is passed to it')}function s(r){"use strict";if(typeof r!=="string"||!e[r]){throw new ReferenceError("The event name does not exist in this event manager: "+r)}return true}r.on=function(r){"use strict";s(r);for(var t=1;t<arguments.length;t++){var n=arguments[t];if(e[r].indexOf(n)===-1){e[r].push(n)}}return this};r.off=function(t){"use strict";switch(arguments.length){case 0:for(var n in e){if(e.hasOwnProperty(n)){r.off(n)}}break;case 1:s(t);e[t].length=0;break;default:s(t);for(var a=1;a<arguments.length;a++){var i=arguments[a];var o=e[t].indexOf(i);if(o!==-1){e[t].splice(o,1)}}break}return this};r.trigger=function(t){"use strict";s(t);var n=[];for(var a=1;a<arguments.length;a++){n.push(arguments[a])}var i=e[t];var o=[];for(var f=0;f<i.length;f++){var u=i[f];try{u.apply(r,n)}catch(c){o.push({listener:u,error:c})}}if(o.length>0){throw o}return this};return r}

The negatives of the current approach include:

  1. this library no longer gets the free updates from the EventJS library so we don't get their performance improvements.
  2. this library no longer gets the free updates from the EventJS library so we don't get their security enhancements.
  3. the type information is broken due to that line I linked above.

Crash reports coming from hasFeature()

We are using "react-native-flagsmith": "1.6.2" in our production iOS/Android apps and we are seeing occasional crash reports coming from within your library on lines where we call flagsmith.hasFeature().

On Android devices it comes through as:
image

On iOS:
image

onChange handler returns updated values in oldFlags object

When I try to access the oldFlags object to check for state updates I get updated latest values.

onChange: (oldFlags, params) => {
  const oldLink = oldFlags["dh_web_link"].value;  // test.com
  const newLink = bulletTrain.getValue("dh_web_link");  // test.com
}

Expected behavior:
I should receive the old value when I access oldLink

Is this something to do with the recent oldFlags fix #22 ?

Decrease unnecessary network requests

I just upgraded to the new flagsmith/react implementation with hooks, and it works fantastic now. Thanks @kyle-ssg for improving the FlagsmithProvider!

But I have noticed that my website went from making 2 network requests on load to 3 that all seem to have the same data in the POST and all get the same response from flagsmith? 🤔

2 of these network requests seem unnecessary to make on load.

When loading the website, this is the waterfall I get from flagsmith endpoint:
Screen Shot 2022-03-24 at 17 41 24

All 3 POST requests hit the same endpoint and have the exact same "payload" and all get the same response. I don't see a need to make 3 requests for this?

Here is my initialization:

      <FlagsmithProvider
        options={{
          environmentID: APP_CONFIG.FLAGSMITH_ENV,
          cacheFlags: true,
          identity: user.sub,
          traits: {
            id: user.sub,
            allowed_company_uids: user.allowed_company_uids,
            preferred_username: user.preferred_username,
          },
        }}
        flagsmith={flagsmith}
      >
        {children}
      </FlagsmithProvider>

Is there a way to optimize the network requests?

It could also be because my app re-renders 3 times in the time-span. But if that's the case I would expect Flagsmith to see that the values are the same as before and not run the init requests again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.