reactjs - props 更改时刷新 React-Native FlatList - 使用 redux 管理状态
问题描述
在您阅读之前 ->> 我确实尝试在我的 FlatList 配置中使用 extraData 道具,但它似乎无法正常工作(可能是因为我使用 Redux 来管理状态?)
我的 FlatList 从我的 API 呈现数据(基本上它显示用户聊天消息)。
当使用此生命周期方法发送每条聊天消息时,我已经能够刷新 FlatList:
componentDidUpdate(prevProps) {
if (prevProps.messages !== this.props.messages) {
this.props.fetchActivityMessages(this.props.navigation.state.params.activityId);
}
}
在外面,它似乎工作正常。但是,这会导致对我的服务器的多个/无限请求数据。例如,如果我在聊天屏幕上使用 console.log(this.props),它会无限地继续 console.log。
这显然是一个主要问题,但这是我发现使用新数据刷新列表而无需重新加载屏幕的唯一方法。
当我尝试使用 extraData 道具时,我尝试了以下操作:
extraData={() => {this.props.fetchActivityMessages()}}
extraData={this.props}
extraData={this.props.messages}
这些都没有使 FlatList 刷新而无需重新加载页面。
任何人都可以帮忙吗?我觉得我要么对 componentDidUpdate 生命周期方法做错了(导致它发出无限请求),要么我没有正确使用 extraData 道具。
我的平面列表(聊天)组件
import { activityMessage, sendActivityMessage, fetchActivityMessages } from '../actions';
import ChatListItem from './ChatListItem';
const ROOT_URL = 'https://mydomain.herokuapp.com';
const io = require('socket.io-client/dist/socket.io');
const socket = io.connect(ROOT_URL);
class ActivityChatForm extends Component {
componentDidMount() {
this.props.fetchActivityMessages(this.props.navigation.state.params.activityId);
}
// Need to fix as it makes infinite requests to the server
//but so far the only way I could get the FlatList to refresh without reloading page
componentDidUpdate(prevProps) {
if (prevProps.messages !== this.props.messages) {
this.props.fetchActivityMessages(this.props.navigation.state.params.activityId);
}
}
handleSubmit = () => {
const { activityId } = this.props.navigation.state.params;
const { sendActivityMessage, messageBody } = this.props;
socket.emit('createMessage', {
from: 'MEE!!',
text: messageBody
}, (data) => {
console.log('Received it', data);
});
sendActivityMessage({
activityId,
messageBody
});
}
renderItem = (message) => {
return <ChatListItem message={message} navigation={this.props.navigation}/>;
}
renderList = () => {
return (
<View>
<FlatList
ref={(ref) => { this.flatListRef = ref; }}
data={this.props.messages}
renderItem={this.renderItem}
keyExtractor={(message, index) => index}
/>
</View>
);
}
render() {
return (
<View>
<CardSection>
{this.renderList()}
</CardSection>
<CardSection>
<Input
value={this.props.messageBody}
onChangeText={text => this.props.activityMessage({ prop: 'messageBody', value: text})}
placeholder="Type your message"
/>
</CardSection>
<CardSection>
<Button
onPress={() => this.handleSubmit()}
buttonText="Send Message"
/>
</CardSection>
</View>
);
}
}
const mapStateToProps = (state) => {
const { messageBody } = state.activityMessage;
const { messages, loading } = state.fetchActivityMessages;
return { messageBody, messages, loading };
};
export default connect(mapStateToProps, {
activityMessage,
sendActivityMessage,
fetchActivityMessages
})(ActivityChatForm);
我的 ChatListItem 组件(用于在 FlatList 中渲染项目)
class ChatListItem extends React.PureComponent {
render() {
const { messageBody } = this.props.message.item;
return (
<View>
<CardSection>
<Text style={styles.titleStyle}>{ messageBody }</Text>
</CardSection>
</View>
);
}
}
export default ChatListItem;
fetchActivityMessages 动作创建者。这用于从我的 API 中提取用户消息数据
export const fetchActivityMessages = (activityId) => {
return async (dispatch) => {
try {
dispatch({ type: FETCH_MESSAGES_INITIATE });
let token = await AsyncStorage.getItem('token');
let { data } = await axios.get(`${ROOT_URL}/activities/${activityId}/chat`, {
headers: { 'x-auth': `${token}` }
});
dispatch({
type: FETCH_MESSAGES_SUCCESS,
payload: data
});
} catch(error) {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
console.log(error.config);
};
};
};
解决方案
首先摆脱“componentDidUpdate()”。就像你说的那样不断触发。这是因为在屏幕上执行的每个操作,它调用“componentDidUpdate”。
其次,extraData 属性需要传递一个状态对象属性,而不是道具。有了道具它什么也做不了。因此,在您的代码中,我认为您需要执行以下操作:
state = {};
...
componentDidMount() {
const myData = this.props.fetchActivityMessages
(this.props.navigation.state.params.activityId);
this.setState({
data: myData
})
}
....
<FlatList
ref={(ref) => { this.flatListRef = ref; }}
data={this.props.messages}
extraData={this.state.data}
renderItem={this.renderItem}
keyExtractor={(message, index) => index}
/>
我说我认为是因为我不确定 redux 部分。Redux 管理您的应用程序状态,但我认为您仍然可以在各个屏幕中设置状态对象。我再次不确定。如果我工作,我们每天都使用 React-Native,但不是 Redux。希望有些帮助 :)
推荐阅读
- python - 雅虎财务错误:“NoneType”对象不可下标
- python - 使用带范围的 for 循环填充空列表时检查用户输入
- ffmpeg - 用于转换 h.265 的最有效的网络格式
- python - 如何在“字段”元组中包含外键字段以使其显示在 Django Admin 的详细视图页面上
- javascript - 带有生命周期钩子的事件驱动 NodeJS 应用程序架构
- r - 使用正则表达式从数据框中提取等位基因特定信息并将其拆分为两个新的数据框
- r - 创建 dplyr 语句以稍后在 R 中进行评估
- excel - 在 VBA 中移动带有他的标题的数组
- javascript - React-native .map undefined 不是对象
- python - 为校准模型拆分保留数据