LobeChat uses Namespace for action labels in DevTools configuration
In this article, we will look at how the action labels use Namespace in LobeChat devtools. I want to provide a bit of an introduction to the terms such action labels, devtools and how/why they come into the picture.
LobeChat uses Zustand for its state management and has DevTools configured for debugging purposes. When you see DevTools configured, you will have action labels for the Zustand.
What is action label?
In the set
, you will have to provide action label, otherwise this action appears as anonymous in your Redux DevTools.
Example from the documentation
addFish: () => set((state) => ({ fishes: state.fishes + 1 }),
undefined,
'jungle/addFish',
),
Action name here is a string.
How does LobeChat configure its action label?
Let’s pick this example found in Session Slice action.
switchSession: (sessionId) => {
if (get().activeId === sessionId) return;
set({ activeId: sessionId }, false, n(`activeSession/${sessionId}`));
},
Action name here is a function named n
. What’s this n function? n is a function returned by a function named setNamespace
at line 31.
const n = setNamespace('session');
setNamespace is imported from storeDebug.ts and has the below code:
export const setNamespace = (namespace: string) => {
return (type: string, payload?: any) => {
const name = [namespace, type].filter(Boolean).join('/');
return payload
? {
payload,
type: name,
} : name;
};
};
This returns an arrow function that has two parameters:
type: string
payload?: any
This below line is interesting.
const name = [namespace, type].filter(Boolean).join('/');
I have never seen this before — applying filter with Boolean
. If you were to execute this in your browser’s console using some strings as shown below:
["session", true].filter(Boolean).join('/')
["session", "true"].filter(Boolean).join('/')
["session", "true"].filter(Boolean).join('/')
["session", "switchSession/true/id-123"].filter(Boolean).join('/')
["session", "switchSession/id-123"].filter(Boolean).join('/')
When you paste the above code in the browser’s console, you will find the results shown as in this screenshot below
I asked ChatGPT to explain this line of code and it has to say this about it:
The line
[namespace, type].filter(Boolean).join('/')
is used to build a string representing the action name for Zustand's store configuration in LobeChat. Let’s break it down and address whyfilter(Boolean)
is used.Code Breakdown
[namespace, type]
:This creates an array containing two values:
namespace
andtype
.
namespace
is likely a string representing a broader category or module.
type
represents the specific action within that namespace, e.g.,activeSession
.
.filter(Boolean)
:Filters out any
falsy
values (e.g.,undefined
,null
,false
, or an empty string) from the array.This ensures the resulting string only includes valid components.
If
namespace
is not provided (e.g.,namespace
isundefined
or''
), it will not be included in the final string.
.join('/')
:Joins the remaining array elements with a
/
separator to create a namespaced action name, e.g.,namespace/type
or justtype
ifnamespace
is absent.
If the payload exists, an object is returned:
return payload
? {
payload,
type: name,
} : name;
};
Below example is from global/action.ts
toggleChatSideBar: (newValue) => {
const showChatSideBar =
typeof newValue === 'boolean' ? newValue : !get().status.showChatSideBar;
get().updateSystemStatus({ showChatSideBar }, n('toggleAgentPanel', newValue));
},
Conclusion here is action name can be an object or a string.
About us:
At Thinkthroo, we study large open source projects and provide architectural guides. We have developed reusable Components, built with tailwind, that you can use in your project.
We offer Next.js, React and Node development services.
Book a meeting with us to discuss your project.