首页 > 解决方案 > 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);
        };
    };
};

标签: reactjsreact-nativereduxreact-reduxreact-native-flatlist

解决方案


首先摆脱“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。希望有些帮助 :)


推荐阅读