チャット機能でよくある、@名前 と入力して、誰宛のメッセージなのかを指定できるメンション機能を実装したいことってあるかと思います。
で、「react-native-controlled-mentions」ライブラリが一番分かりやすくて実装が簡単だったので、実装手順を備忘録としてまとめ。
GitHub のページはこちらです。
GitHub – dabakovich/react-native-controlled-mentions: Fully controlled React Native mentions component
https://github.com/dabakovich/react-native-controlled-mentions
まず、下記コマンドでライブラリをインストールします。
npm install --save react-native-controlled-mentions
なお、npx pod-install も実行しましたが、こちらは不要みたいでした。
あとは GitHub のサンプルコードをまるっとコピー&ペーストしていきます。
まず、必要なコンポーネントなどをインポートし、下記を追加します。
import { MentionInput, MentionSuggestionsProps, Suggestion, replaceMentionValues } from 'react-native-controlled-mentions';
const renderSuggestions: (suggestions: Suggestion[]) => FC<MentionSuggestionsProps> = (suggestions) => (
{keyword, onSuggestionPress},
) => {
if (keyword == null) {
return null;
}
return (
<ScrollView style={styles.mentionUserList}>
{suggestions
.filter(one => one.name.includes(keyword))
.map(one => (
<ListItem bottomDivider key={one._id} onPress={() => onSuggestionPress(one)} pad={10} containerStyle={styles.mentionUserListItem}>
<Avatar size={30} rounded source={{ uri: one.avatar }} />
<ListItem.Title>{one.name}</ListItem.Title>
</ListItem>
))
}
</ScrollView>
);
};
こちらは、入力欄に @ が入力されたタイミングで表示されるユーザ一覧のリストです。
私は React Native Elements の ListItem を使用しました。
次に入力欄を下記のように変更します。
const renderMentionSuggestions = renderSuggestions(this.state.members);
return (<MentionInput
value={this.state.text}
onChange={text => this.setState({ text: text })}
partTypes={[{
trigger: '@',
renderSuggestions: renderMentionSuggestions,
textStyle: { fontWeight: 'bold', color: '#608CDB' },
}]}
placeholder='メッセージを入力' />);
なお、私は「react-native-gifted-chat」ライブラリを使用しているため、renderComposer に上記を指定しました。
this.state.members にユーザ一覧のデータが格納されており、それを 1つ前で定義した renderSuggestions に渡します。
そして、partTypes で、@ が入力されたらユーザ一覧のリストを表示するように指定しています。
また、リストのユーザがタップされて入力欄に代入された時、そのユーザ名のスタイルを指定することができます。
私はテキストを太くし、文字色を青色に変更するように指定しました。
そして、<GiftedChat> コンポーネントに下記を追加します。
parsePatterns={(linkStyle) => [
{ pattern: /@\S+/, style: styles.linkStyle, onPress: this.pressMention },
]}
こちらを追加すると、@名前 の部分がタップ可能になります。
this.pressMention に @名前 をタップした時の処理を追加できますので、任意の処理を追加してください。
また、styles.linkStyle で @名前 の部分のテキストスタイルを指定できますので、こちらも任意のスタイルを指定してください。
なお引数の linkStyle を使うと、文字色が白色で下線が引かれたレイアウトになります。
最後に、メッセージを送信する際、入力テキストを下記の処理を実行して文字の置換をしています。
const text = replaceMentionValues(this.state.text, ({name}) => `@${name} `);
上記を実行しないで送信すると、入力欄では @名前 となっていた部分が、@[名前](123) となってしまうので、@名前 に置き換えています。
基本的な機能は上記で実装できます!
実は iOS で、入力欄でメンション入力後、引き続きテキストを入力すると、メンションのテキストレイアウトが引き継がれてしまうという事故が発生しています…。
が、これさえ直れば実装はとても簡単だし、レイアウトの調整も簡単だしで、かなりおすすめです!
まだ時間的に猶予はあるので、引き続き調整していきたいと思います。
以上、React Native でチャットのメンション機能を実装できるライブラリ「react-native-controlled-mentions」のご紹介でした。
ご参考になれば幸いです。