import { AutoCompleteSuggestionHeader } from "stream-chat-react-native";
import { Text } from "react-native";
<Channel
AutoCompleteSuggestionHeader={({ queryText, triggerType }) => {
if (triggerType === "command") {
return <Text>Command Header Component</Text>;
} else if (triggerType === "emoji") {
return <Text>Emoji Header Component</Text>;
} else {
return (
<AutoCompleteSuggestionHeader
queryText={queryText}
triggerType={triggerType}
/>
);
}
}}
>
{/* The underlying components */}
</Channel>;Custom Autocomplete Suggestion List
Autocomplete suggestion list components can be customized via Channel props:
Best Practices
- Preserve default components for triggers you don't customize to keep expected behavior.
- Keep list rendering lightweight; suggestion updates happen on every keystroke.
- Use
keyboardShouldPersistTaps="always"in custom lists to avoid dismissing the keyboard. - Normalize
triggerTypemapping (/,:,@) to avoid mismatched UI. - Ensure
onSelectupdates the composer state rather than mutating input directly.
Header and item components are used inside the list's FlatList. These props let you customize the header, items, or the entire list.
The available suggestion trigger types are:
commandfor/emojifor:mentionfor@
You can render custom UI for specific triggers and fall back to defaults for the rest.
Customizing Header component
The header renders at the top of the list and is customized via AutoCompleteSuggestionHeader.
The props for the component are:
triggerType: The trigger type of the suggestion list.queryText: The value to display in the header.
An example for the same would be as follows:
Note: Return the default AutoCompleteSuggestionHeader to keep default behavior for a trigger.
Customizing Item Component
Customize list items via the AutoCompleteSuggestionItem prop on Channel.
The props for the component are as follows:
triggerType: The trigger type of the suggestion list.itemProps: Varies by trigger.commandhasnameandargs,emojiis anEmoji, andmentionisSuggestionUser<Us>.
import { Avatar, AutoCompleteSuggestionItem } from "stream-chat-react-native";
import { Text, View } from "react-native";
<Channel
AutoCompleteSuggestionItem={({ itemProps, triggerType }) => {
if (triggerType === "command") {
return (
<View>
<Text>{itemProps.name}</Text>
<Text>{itemProps.args}</Text>
</View>
);
} else if (triggerType === "mention") {
const { id, image, name, online } = itemProps;
return (
<View>
<Avatar image={image} name={name} online={online} size={30} />
<Text>{itemProps.name}</Text>
</View>
);
} else {
return (
<AutoCompleteSuggestionItem
itemProps={itemProps}
triggerType={triggerType}
/>
);
}
}}
>
{/*The underlying components*/}
</Channel>;Note: Return the default AutoCompleteSuggestionItem to keep default behavior for a trigger.
Customizing the AutoComplete suggestion list
You can also replace the entire list via AutoCompleteSuggestionList on Channel.
The props available to the component are:
AutoCompleteSuggestionHeader- The header component to be used in the list.AutoCompleteSuggestionItem- The item component to be used in the list.
Example:
import {
AutoCompleteSuggestionHeader,
AutoCompleteSuggestionItem,
useMessageComposer,
useStateStore,
Channel,
} from "stream-chat-react-native";
import { FlatList, Text, View } from "react-native";
import { TextComposerState, SearchSourceState } from "stream-chat";
const textComposerStateSelector = (state: TextComposerState) => ({
suggestions: state.suggestions,
text: state.text,
});
const searchSourceStateSelector = (nextValue: SearchSourceState) => ({
items: nextValue.items,
});
const CustomAutoCompleteSuggestionList = () => {
const messageComposer = useMessageComposer();
const { textComposer } = messageComposer;
const { suggestions } = useStateStore(
textComposer.state,
textComposerStateSelector,
);
const { items } =
useStateStore(suggestions?.searchSource.state, searchSourceStateSelector) ??
{};
const trigger = suggestions?.trigger;
const queryText = suggestions?.query;
const triggerType = {
"/": "command",
":": "emoji",
"@": "mention",
}[trigger ?? ""];
const onSelect = (item) => {
// Handle the selection of the item
console.log("Selected item:", item);
};
if (triggerType === "command") {
return (
<View>
<View>
<Text>Command suggestions for {queryText}</Text>
</View>
{data.map((item) => (
<AutoCompleteSuggestionItem
itemProps={item}
key={item.name}
triggerType={triggerType}
/>
))}
</View>
);
} else if (triggerType === "emoji") {
return (
<FlatList
data={data}
keyboardShouldPersistTaps="always"
ListHeaderComponent={
<AutoCompleteSuggestionHeader
queryText={queryText}
triggerType={triggerType}
/>
}
renderItem={({ index, item }) => (
<TouchableOpacity
onPress={() => {
onSelect(item);
}}
>
<Text>{item.unicode}</Text>
</TouchableOpacity>
)}
/>
);
} else {
return (
<View>
<AutoCompleteSuggestionHeader
queryText={queryText}
triggerType={triggerType}
/>
{data.map((item) => (
<AutoCompleteSuggestionItem
itemProps={item}
key={item.name}
triggerType={triggerType}
/>
))}
</View>
);
}
};
<Channel AutoCompleteSuggestionList={CustomAutoCompleteSuggestionList}>
{/*The underlying components*/}
</Channel>;Note: Return the default AutoCompleteSuggestionList to keep default behavior for a trigger.