无限循环使用React Native Hooks和Redux来获取useEffect中的数据

时间:2020-06-21 16:10:50

标签: android reactjs react-native redux use-effect

我无法使用useEffect解决与React Hooks和Redux的无限循环有关的问题。 我已经阅读了许多有关useEffect的文章(https://overreacted.io/a-complete-guide-to-useeffect/https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencieshttps://www.robinwieruch.de/react-hooks-fetch-data),但仍然无法避免这种无限循环。

我确实有一个带有2个选项卡的应用程序,其中一个是传输列表,另一个是活动传输的摘要。 这个想法是要有一个可以预订的运输清单,并且每当完成时,在另一个选项卡中更新活动的运输。 应用程序的周期应类似于:

  • 登录App->没有有效的传输。 (调度操作以获取数据)。
  • 单击“传输列表”选项卡(调度操作以获取传输列表)。
  • 预订运输工具(分派一项操作以使用选定的运输工具更新活动运输工具)
  • 单击“活动的传输”选项卡,然后查看传输的信息。

其背后的想法是,每当更新活动传输的状态时,都必须重新渲染活动传输屏幕,因为它是useEffect的依赖项,但是它会触发无限循环。

我明白为什么。为了从数据库中获取活动的传输,我使用了典型的调度序列(Request,Success,Error),这些调度会更改依赖项的状态。这会触发无限循环,因为每次状态更改时,屏幕都会重新呈现,并且传输列表也存在相同的问题。

即使知道这一点,我仍然不知道如何解决。

我正在使用的活动屏幕是下一个屏幕:

ActiveTransport屏幕:

export default function ActiveTransportScreen() {

const dispatch = useDispatch();
const isLoading = useSelector(state => state.activeTransport.isLoading);
const transport = useSelector(state => state.activeTransport.transport);

useEffect(() => {
    dispatch(activeTransportActions.getActiveTransport());
}, [transport]);

if (isLoading) {
    return (
        <View style={styles.container}>
            <Text>Cargando</Text>
        </View>
    )
}

if (!transport) {
    return (
        <View style={styles.container}>
            <Text>No hay ningun transporte activo</Text>
        </View>
    )
}


return (
    <View style={styles.container}>
        <View style={styles.item}>
            <Text>Lugar de retirada: {transport.removalPlace} </Text>
        </View>

        <View style={styles.containerButtons}/>
        <TouchableHighlight
            style={{...styles.openButton, backgroundColor: "#2196F3"}}
            onPress={() => {
            }}
        >
            <Text style={modalStyles.textStyle}>Completar hito</Text>
        </TouchableHighlight>

        <TouchableHighlight
            style={{...styles.openButton, backgroundColor: "#2196F3"}}
            onPress={() => {
                dispatch(activeTransportActions.cancelTransport());
            }}
        >
            <Text style={modalStyles.textStyle}>Cancelar</Text>
        </TouchableHighlight>
    </View>
);

}

背后的想法是,每当活动传输状态更新时,便能够重新渲染ActiveScreen。这可以从传输列表中完成。

export default function TransportList() {

const dispatch = useDispatch();

const isLoading = useSelector(state => state.transportList.isLoading);
const transportsTablesList = useSelector(state => state.transportList.transports);
const isRefreshing = useSelector(state => state.transportList.isRefreshing);
const modalVisible = useSelector(state => state.modalTransportReducer.modalVisible);
const userActiveTransportId = useSelector(state => state.activeTransport.id);



const onRefresh = React.useCallback(() => {
    dispatch(transportActions.refreshTransportList());
}, []);

useEffect( () => {
    dispatch(transportActions.getAll());
}, [transportsTablesList ]);


if (isLoading) {
    return (
        <View style={styles.container}>
            <Text>Cargando</Text>
        </View>
    )
}

if (modalVisible) {
    return (
        <ModalTransport/>
    );
}

if(userActiveTransportId){
    return (
        <View style={styles.container}>
            <Text>¡Ya tienes un transporte activo!</Text>
        </View>
    )
}

return (
    <View style={styles.container}>

        <ScrollView horizontal={true}
                    refreshControl={<RefreshControl refreshing={isRefreshing} onRefresh={onRefresh}/>}>
            <FlatList
                data={transportsTablesList}
                ListHeaderComponent={HeaderListTransport}
                keyExtractor={(item) => item.id.toString()}
                renderItem={({item}) => (RowListTransport(item))}
            />
        </ScrollView>
    </View>
);

}

    const initialState =
    {
        isLoading: false,
        id: null,
        transport: null,
        accomplishment: null,
        state: null,
        isRefreshing: false
    };

export function activeTransport(state = initialState, action) {

switch (action.type) {

    case activeTransportConstants.BOOK_TRANSPORT_REQUEST:
        return {
            ...state,
            isLoading: true,
            id: null,
        };

    case activeTransportConstants.BOOK_TRANSPORT_SUCCESS:
        return {
            ...state,
            isLoading: false,
            transport: action.transport,
            transportId: action.transportId
        };


    case activeTransportConstants.BOOK_TRANSPORT_ERROR:
        return {
            ...state,
            isLoading: false,
            transport: null,
            transportId: null
        };

    case activeTransportConstants.GET_ACTIVE_TRANSPORT_REQUEST:
        return {
            ...state,
            isLoading: true,
        };

    case activeTransportConstants.GET_ACTIVE_TRANSPORT_SUCCESS:
        return {
            ...state,
            isLoading: false,
            id: action.payload.id,
            transport: action.payload.transport,
            accomplishment: action.payload.accomplishment,
            state: action.payload.state
        };

每次用户预订运输时,下一个Modal都会调度操作以更新数据库并获取活动的运输,因此,应该使用新运输的信息重新呈现ActiveTransport选项卡。

export default function ModalTransport() {

const dispatch = useDispatch();
const modalVisible = useSelector(state => state.modalTransportReducer.modalVisible);
const transportSelected = useSelector(state => state.modalTransportReducer.transportSelected);

return(
    <View style={modalStyles.centeredView}>
        <Modal
            animationType="slide"
            transparent={true}
            visible={modalVisible}
            onRequestClose={() =>
                {
                        dispatch(transportActions.refreshTransportList());
                        // dispatch(activeTransportActions.getActiveTransport());
                }
            }
        >
            <View style={modalStyles.centeredView}>
                <View style={modalStyles.modalView}>
                    <Text style={modalStyles.modalText}>Transporte</Text>
                    <Text style={{width: 300, height: 50}}><Text style={{fontWeight: 'bold'}}> Lugar de retirada:</Text> {transportSelected.transportEntity.removalPlace}</Text>
                    <Text style={{width: 300, height: 50}}><Text style={{fontWeight: 'bold'}}>Lugar de devolución: </Text> {transportSelected.transportEntity.returnPlace}</Text>
                    <Text style={{width: 300, height: 50}}><Text style={{fontWeight: 'bold'}}>Cliente: </Text>{transportSelected.transportEntity.customer}</Text>
                    <Text style={{width: 300, height: 50}}><Text style={{fontWeight: 'bold'}}> Carga: </Text>{transportSelected.transportEntity.load}</Text>
                    <Text style={{width: 300, height: 50}}><Text style={{fontWeight: 'bold'}}>Fecha: </Text> {transportSelected.transportEntity.date} </Text>
                    <Text style={{width: 300, height: 50}}><Text style={{fontWeight: 'bold'}}>Fecha de caducidad: </Text>{transportSelected.transportEntity.expiryDate} </Text>

                    <View style={{flexDirection: 'row'}}>
                        <TouchableHighlight
                            style={{...modalStyles.openButton, backgroundColor: "#2196F3"}}
                            onPress={() => {
                                dispatch(transportActions.bookTransport(transportSelected.id));
                                dispatch(modalTransportActions.closeModal());
                            }}
                        >
                            <Text style={modalStyles.textStyle}>Reservar</Text>
                        </TouchableHighlight>

                        <TouchableHighlight
                            style={{...modalStyles.openButton, backgroundColor: "#2196F3"}}
                            onPress={() => {
                                dispatch(modalTransportActions.closeModal())
                            }}
                        >
                            <Text style={modalStyles.textStyle}>Cancelar</Text>
                        </TouchableHighlight>
                    </View>
                </View>
            </View>
        </Modal>
    </View>
);

}

我不知道该怎么办。我知道传输是useEffect中唯一的依赖项,每次更改时都必须重新呈现它,但是我不知道如何隔离每次更改状态的请求,成功和错误的顺序。 我只是从状态中选择运输方式,而不是其他部分。

我曾经尝试过useCallback和useMemo,但仍然存在相同的问题。

我该怎么办?

希望您能帮助我。

非常感谢您。

0 个答案:

没有答案