首页 文章

在道具改变时刷新React-Native FlatList - 使用redux来管理状态

提问于
浏览
1

在您阅读之前 - >>我确实尝试在我的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 prop时,我尝试了以下方法:

extraData={() => {this.props.fetchActivityMessages()}}
extraData={this.props}
extraData={this.props.messages}

其中没有一个能够在不重新加载页面的情况下刷新FlatList .

有人可以帮忙吗?我觉得我在使用componentDidUpdate生命周期方法做错了(导致它发出无限请求)或者我没有正确使用extraData prop .

My FlatList(Chat) Component

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);

My ChatListItem component (used to renderItem in 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;

The fetchActivityMessages action creator. This is used to pull user message data from my 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);
        };
    };
};

1 回答

  • 0

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

相关问题