我正在React Native中构建一个聊天应用程序,但是每次渲染时,这些组件都重复渲染20次以上。我尝试使用PureComponent
和memo
,但还是没有。
我将结构分为3个组成部分:Chat.js
和SubChat.js
,这是Apollo's doc上使用subscribeToMore
显示的结构,并在其中添加了Message.js
显示实际消息。
Chat.js
class Chat extends PureComponent {
render() {
return (
<View style={styles.container}>
<Query
query={GET_MESSAGES_QUERY}
options={{ fetchPolicy: 'network-only'}}
>
{({ subscribeToMore, ...result }) => (
<SubChat
{...result}
subscribeToNewMessages={() =>
subscribeToMore({
document: MESSAGE_SUBSCRIPTION,
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const newMessage = subscriptionData.data.newMessage
if(newMessage.user.id === authId && newMessage.isTyping === true) {
return {
messages: prev.messages
}
}
const indicatorMessages = prev.messages.filter(message => message.isTyping === true && message.user.id !== authId)
if(indicatorMessages) {
prev.messages = prev.messages.filter(message => !indicatorMessages.includes(message))
}
const combinedMessages = prev.messages.concat([newMessage])
return {
messages: combinedMessages
}
}
})
}
/>
)}
</Query>
</View>
)
}
}
SubChat.js
const SubChat = ({
subscribeToNewMessages,
...results
}) => {
useEffect(() => {
subscribeToNewMessages()
}, [])
const [ chatMessage, setChatMessage ] = useState('')
// some logic relating to handling message mutation as well as message query
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === "ios" ? "padding" : null}
keyboardVerticalOffset={180}
>
<SafeAreaView style={styles.container}>
<FlatList
data={messages}
renderItem={({ item, index }) =>
<Message
item={item}
index={index}
/>
}
keyExtractor={item => item.id.toString()}
/>
<View style={[styles.input, focus && styles.onFocus]}>
<View style={styles.inputContainer} >
<TextInput
style={styles.textInput}
label="Chat"
value={chatMessage}
onChangeText={setChatMessage}
placeholder = "Write a message"
authoCapitalize = "none"
multiline
/>
</View>
</View>
</SafeAreaView>
</KeyboardAvoidingView>
)
}
export default React.memo(SubChat)
最后是Message.js
const Message = ({
item,
}) => {
const { text } = !!item && item
return (
<View style={styles.container} >
<Text>{text}</Text>
</View>
)
}
export default React.memo(Message)
我不确定是不是导致重新提交的订阅,所以我尝试了以下操作,但仍然没有成功:
useEffect(() => {
subscribeToNewMessages()
return () => subscribeToNewMessages()
}, [])
更新
我已经将PureComponent
的{{1}}转换为常规SubChat.js
,并包含了Component
:
shouldComponentUpdate
我还将shouldComponentUpdate(nextProps, nextState) {
const { data, members, authId, navigation } = this.props && this.props
if (data !== nextProps.data) {
return true
}
if (members !== nextProps.members) {
return true
}
if (authId !== nextProps.authId) {
return true
}
if (navigation !== nextProps.navigation) {
return true
}
if (text !== nextState.text) {
return true
}
if (image !== nextState.image) {
return true
}
if (largImage !== nextState.largImage) {
return true
}
if (chatterId !== nextState.chatterId) {
return true
}
if (myPosts !== nextState.myPosts) {
return true
}
if (theirPosts !== nextState.theirPosts) {
return true
}
if (keycode !== nextState.keycode) {
return true
}
return false
}
的功能组件转换为基于类的组件,并包含了Message.js
:
shouldComponentUpdate
但是,发生相同数量的重新渲染。父组件class Message extends Component {
shouldComponentUpdate (nextProps, nextState) {
if(this.props.item !== nextProps.item) {
return true
}
return false
}
render() {
return (
<View style={styles.container} >
</View>
)
}
}
仅渲染一次,Chat.js
渲染两次,SubChat.js
渲染大约20次。