Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

liveblocksEnhancer does not mix in LiveblocksContext to the state #1644

Open
johannes-lindgren opened this issue May 30, 2024 · 1 comment
Open
Labels
documentation Related to the public documentation enhancement New feature or request triage needed The issue needs to be reviewed by the team

Comments

@johannes-lindgren
Copy link

What is the improvement or update you wish to see?

When you use liveblocksEnhancer, the liveblocks state should be automatically mixed into the store's state.

For example, given the following configuration:

export const store = configureStore({
  reducer: {
  },
  enhancers: (getDefaultEnhancers) =>
    getDefaultEnhancers().concat(
      liveblocksEnhancer({
        client,
      }),
    ),
})

export type RootState = ReturnType<typeof store.getState>
export const useAppSelector = useSelector.withTypes<RootState>()

liveblocks should be present on the state. But since it's not, I get a type error when I try to access the liveblocks state in a selector:

const WhoIsHere: FunctionComponent = () => {
  const othersUsersCount = useAppSelector(
    (state) => state.liveblocks.others.length, // <--- type error here since `liveblocks` is not defined on the state type.
  )

  return (
    <div className="who_is_here">
      There are {othersUsersCount} other users online
    </div>
  )
}

This happens because liveBlocksEnhancer is declared as

declare const liveblocksEnhancer: <TState>(options: {
    client: Client;
    storageMapping?: Mapping<TState> | undefined;
    presenceMapping?: Mapping<TState> | undefined;
}) => StoreEnhancer;

where the return type StoreEnhancer does not have type arguments. This means that the liveblocks property does not get mixed into the state, and users of this library have to assert the type manually.

I would expect something like:

declare const liveblocksEnhancer: <TState>(options: {
    client: Client;
    storageMapping?: Mapping<TState> | undefined;
    presenceMapping?: Mapping<TState> | undefined;
}) => StoreEnhancer<
        Record<string, never>,
        WithLiveblocks<Record<string, never>, JsonObject, BaseUserMeta>
      >;

Possibly with something else as the first type argument, for I don't know if this liveblocksEnhancer augments the store type.

Ex. https://liveblocks.io/docs/api-reference/liveblocks-react

@johannes-lindgren johannes-lindgren added documentation Related to the public documentation enhancement New feature or request triage needed The issue needs to be reviewed by the team labels May 30, 2024
@johannes-lindgren
Copy link
Author

johannes-lindgren commented May 31, 2024

When I run the code from the example in the documentation, everything works, but I get the following warning from Redux (as in this issue):

Unexpected key "liveblocks" found in previous state received by the reducer. Expected to find one of the known reducer keys instead: "mySlice". Unexpected keys will be ignored.

I managed to work around it in this way, by creating a dummy reducer:

export const store = configureStore({
  reducer: {
    mySlice: mySlice.reducer,
    liveblocks: createSlice({
      name: 'liveblocks',
      initialState: {
        others: [],
        status: 'initial',
        connection: 'authenticating',
        isStorageLoading: true,
      } satisfies WithLiveblocks<
        Record<string, never>,
        JsonObject,
        BaseUserMeta
      >['liveblocks'],
      reducers: {},
    }).reducer,
  },
  enhancers:
    apiKey === undefined
      ? undefined
      : (getDefaultEnhancers) =>
          getDefaultEnhancers().concat(
            liveblocksEnhancer({
              client: createClient({
                publicApiKey: apiKey,
              }),
              storageMapping: {
                concepts: true,
                conversations: true,
              },
            }),
          ),
})

In this way, I don't need to asser the type of liveblocksEnhancer, but the dummy reducer is no so pretty. Is this the right thing to do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Related to the public documentation enhancement New feature or request triage needed The issue needs to be reviewed by the team
Projects
None yet
Development

No branches or pull requests

1 participant