launchdarkly / js-client-sdk

LaunchDarkly Client-side SDK for Browser JavaScript
Other
112 stars 65 forks source link

Change User dynamically #166

Closed pwan001-dev closed 5 years ago

pwan001-dev commented 5 years ago

Since the user is provided as a parameter to the HoC, the user is bound to the "instance" of the Provider component that's returned by the withLDProvider HoC. That means, any time the user sign in status changes in our app, we must create a new wrapped Provider component, which will re-instantiate the entire DOM that's beneath the Provider.

Instead of using a HoC, I'm curious why we can't just provide at least the User via props to the Provider component, and have the Provider re-initialize if the User changes.

bwoskow-ld commented 5 years ago

Hi @pwan001-dev,

While the LaunchDarkly SDK for React requires that it be associated with a single user, the SDK does provide a mechanism for switching to a different user context without creating new provider components. This mechanism is essential for situations like the one you described where there are changes to the user sign in status.

To do so, you'll want to use the identify function on your underlying ldclient instance. Please note, as mentioned in the React SDK documentation, all logic exposed in the JavaScript API is equally accessible in the React SDK.

Let me know if this addresses your question.

Cheers, Ben

pwan001-dev commented 5 years ago

That worked, thank you!

Unrelated to the React client, but I noticed that you can't clear the user after it has been initialized by doing ldClient.identify({key: undefined}) (or null). My assumption would be that it would generate a new random hash after being set to an undefined/null value, but I guess we just need to generate our own random hash to clear the user when signing out.

Thanks again! That saved me a lot of headaches!

bwoskow-ld commented 5 years ago

Hi @pwan001-dev,

Rather than doing what you're doing, you can tell identify that you want to represent an anonymous user by specifying anonymous: true. See this section of the docs for more information. Doing so will force the SDK to generate a unique key for that logged out user -- a key which is persistent across page refreshes such that the user remains having the same flag variations.

Note that this requires version 2.10.0 of the SDK; earlier versions require that you generate the user key yourself.

pwan001-dev commented 5 years ago

Thank you @bwoskow-ld ! It appears my quick scanning of the documentation was insufficient. It's all there, just not where I expected at a glance.

You have been very helpful, thanks again!

TwisterMc commented 2 years ago

Anyone have an example of how to do this with React/JS? The documentation says the following but client is not defined and there seems to be nothing telling me what client is supposed to be.

client.identify(newUser, hash, function() {
  console.log("New user's flags available");
});
louis-launchdarkly commented 2 years ago

Hello @TwisterMc, for the usage of LaunchDarkly with React, we recommend you to look at this documentation for the React SDK https://docs.launchdarkly.com/sdk/client-side/react/react-web and try out the React client-side SDK. That should fit your use case better. Please let us know if you have any questions about using the React client-side SDK.

TwisterMc commented 2 years ago

I have had a million questions and have been searching the internet for the past week for answers. We got it working, but the documentation sure does leave a lot of gaps or makes a lot of assumptions. I want to love LaunchDarkly but it's been a tough week.

vancy-pants commented 2 years ago

In our React app, I figured out the client referred to in client.identify is the ldClient that is exposed after using the withLDConsumer HOC. The same way that flags are exposed, ldClient is also exposed and can be used in the component

eli-darkly commented 2 years ago

@TwisterMc, we're sorry about any gaps in documentation. Feedback from customers is very helpful in finding where those gaps are, and you're also always welcome to open a GitHub issue in the relevant project. I don't think it is nit-picking to say that posting an issue in https://github.com/launchdarkly/react-client-sdk/issues is a better way to get prompt and relevant information about the React SDK, both from LaunchDarkly and from other users, than posting a comment in a different project on an issue that's been closed for over two years. I'm leaving this comment here now to encourage everyone to put their comments in a forum where other React developers are more likely to see them. We happily answer questions on GitHub all the time, but this was not an ideal way to go about it— both in terms of visibility, and because the maintainers of this project, js-client-sdk, are mainly not React developers.

jamesopti commented 2 years ago

@TwisterMc Does client.identify do a deep merge or a replace of the user object passed?

Clarification in the docs for this would be quite helpful for folks using single page apps where things like the URL can change a lot.

I tried looking in launchdarkly-js-sdk-common but it appears that code is not open source and intentionally minified in distribution bundles :/

eli-darkly commented 2 years ago

@jamesopti All of the SDK code is open-source. If you're ever unsure of where the GitHub project is for a package, there is a link to it from the NPM information page for that package. In this case it is https://github.com/launchdarkly/js-sdk-common.

To answer your original question (though in the future it would really be best to put such questions in a new issue— comments on old issues can easily be missed), identify always changes the user properties to exactly the ones that were passed in the user parameter. It does not do any merging with any previous properties, and I'm not sure why the docs for this method would lead you to believe that they are merged; the user parameter is described as "The user properties", not "User properties to be added to previous user properties."

codebymark commented 2 years ago

Just so I am 100% clear.. is possible or not possible across any method in the JS SDK (or any other sdk) to incrementally add user attributes to an LD user?

If not, I would like to say that merging user attributes would be a very helpful feature. :)

eli-darkly commented 2 years ago

@codebymark You can always find out what user attributes the SDK is currently using with LDClient.getUser(), and then it is easy to modify that object in whatever way you want, and then tell the SDK to set the current user to those attributes with LDClient.identify().

I want to be very clear about what this actually does, though, because phrases like "incrementally add to an LD user" can mean different things to different people. The SDK's concept of "current user" means "the set of user properties that we have requested feature flag values for." Whenever you pass different properties to identify(), you have changed the current user and so it will re-request flag values from LaunchDarkly— since flag rules might depend on any of those attributes that you've changed.

However, the SDK only knows about the specific set of attributes you gave it. You can't use it to get some previous user attributes out of LaunchDarkly that aren't already known to your code. The Users page in the LaunchDarkly dashboard is a view onto analytics data that LD has received from the SDK; it is not a database that the SDK can query. So in my answer above, you can incrementally add attributes to a user as long as you already knew what the previous attributes were (that is, they are the ones that you previously passed to the SDK with initialize or identify).

In other words, if your code is starting from scratch with an LDClient that has been initialized with no attributes except {key: "some-user-key"}... it is going to use exactly that, and that's what you will be getting flag values for. It is not going to get some other attributes that were associated with the key "some-user-key" at some point in the past.

eli-darkly commented 2 years ago

@codebymark I don't mean to be rude but I really would like, as I said to @jamesopti, for any further questions on the general subject of user attributes to be put in a new issue. This is a closed issue that isn't about that— it had a very general title, but it was specifically about React behavior.

Also, if you haven't already, you may want to read the product documentation page on the Users list, which addresses some of what I mentioned about attributes from the past not being visible to the SDKs. There isn't any "merging" behavior for this data, either— if you start out using {key: "some-user-key", name: "a"} in an SDK and then a different time you use {key: "some-user-key", email: "b"}, what will end up in the Users list is either the one with name or the one with email, not both.