React native 如何在同一组件中使用react redux控制加载标志?
我用React native 如何在同一组件中使用react redux控制加载标志?,react-native,react-redux,React Native,React Redux,我用react redux创建了一个项目,我的项目有很多城市,点击每个城市就会导航到我的类组件TheaterList.js 我设置我的reducer有一个加载标志(默认值为true,当获取数据成功后返回false)和我的动作MOVIELIST\u剧院,下面是我的MovieListReducer.js代码: import { MOVIELIST_MAINACTIVITY, MOVIELIST_THISWEEK, MOVIELIST_THEATER, MOVIELIST_TIME
react redux
创建了一个项目,我的项目有很多城市,点击每个城市就会导航到我的类组件TheaterList.js
我设置我的reducer有一个加载
标志(默认值为true
,当获取数据成功后返回false
)和我的动作MOVIELIST\u剧院
,下面是我的MovieListReducer.js
代码:
import {
MOVIELIST_MAINACTIVITY,
MOVIELIST_THISWEEK,
MOVIELIST_THEATER,
MOVIELIST_TIME,
MOVIE_DETAIL
} from '../actions/types';
const INITIAL_STATE = {
mainMovie: [],
thisWeek: [],
theaterList: [],
timeList: [],
movieDetail: [],
loading: true
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case MOVIELIST_MAINACTIVITY:
return {
...state,
mainMovie: action.payload
};
case MOVIELIST_THISWEEK:
return {
...state,
thisWeek: action.payload
};
case MOVIELIST_THEATER:
return {
...state,
theaterList: action.payload,
loading: false
};
case MOVIELIST_TIME:
return {
...state,
timeList: action.payload
};
case MOVIE_DETAIL:
return {
...state,
movieDetail: action.payload
};
default:
return state;
}
};
这是我的类组件TheaterList.js
:
import React, { Component } from 'react';
import { View, Text, FlatList } from 'react-native';
import { ListItem } from 'react-native-elements';
import { connect } from 'react-redux';
import { fetchTheater } from '../actions';
import { Spinner } from './common';
class TheaterList extends Component {
constructor(props) {
super(props);
this.renderItem = this.renderItem.bind(this);
const { enCity } = this.props.navigation.state.params;
this.state = {
navigation: this.props.navigation,
enCity
};
}
componentDidMount() {
this.props.fetchTheater({ enCity: this.state.enCity });
}
renderItem({ item }) {
// some view tag
}
render() {
const theaters = this.props.theaterList;
// the default is true when fetch data succeed then return it with false
if (this.props.loading) {
return (
<Spinner text='Loading...' />
);
}
return (
<View style={{ flex: 1 }}>
<FlatList
data={theaters}
renderItem={this.renderItem}
numColumns={1}
horizontal={false}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const mapStateToProps = (state) => {
const theaterList = state.listType.theaterList;
const loading = state.listType.loading;
return { theaterList, loading };
};
const styles = {
// some style settings
};
export default connect(mapStateToProps, { fetchTheater })(TheaterList);
import {
MOVIELIST_MAINACTIVITY,
MOVIELIST_THISWEEK,
MOVIELIST_THEATER,
MOVIELIST_TIME,
MOVIE_DETAIL
} from './types';
export const fetchMainMovieList = () => {
return (dispatch) => {
fetch('https://obscure-reaches-65656.herokuapp.com/api?city=Taipei&theater=Centuryasia')
.then(response => response.json())
.then(responseData => {
dispatch({ type: MOVIELIST_MAINACTIVITY, payload: responseData[0].movie });
})
.catch((error) => console.log(error));
};
};
export const fetchThisWeek = () => {
return (dispatch) => {
fetch('https://obscure-reaches-65656.herokuapp.com/api/thisWeek')
.then(response => response.json())
.then(responseData => {
dispatch({ type: MOVIELIST_THISWEEK, payload: responseData[0].movie });
})
.catch((error) => console.log(error));
};
};
export const fetchTheater = ({ enCity }) => {
return (dispatch) => {
fetch(`https://obscure-reaches-65656.herokuapp.com/api/drivers?city=${enCity}&lng=121.584065&lat=25.041317`)
.then(response => response.json())
.then(responseData => {
console.log(responseData);
dispatch({ type: MOVIELIST_THEATER, payload: responseData });
})
.catch((error) => console.log(error));
};
};
export const fetchTime = ({ enCity, theater }) => {
return (dispatch) => {
fetch(`https://obscure-reaches-65656.herokuapp.com/api?city=${enCity}&theater=${theater}`)
.then(response => response.json())
.then(responseData => {
dispatch({ type: MOVIELIST_TIME, payload: responseData[0].movie });
})
.catch((error) => console.log(error));
};
};
export const fetchDetail = ({ enCity, cnName }) => {
return (dispatch) => {
fetch(`https://obscure-reaches-65656.herokuapp.com/api/detail?city=${enCity}&movie=${cnName}`)
.then(response => response.json())
.then(responseData => {
dispatch({ type: MOVIE_DETAIL, payload: responseData[0].movie });
})
.catch((error) => console.log(error));
};
};
那么,如果使用相同的类组件,如何使用react redux
准确地设置loading
标志呢
任何帮助都将不胜感激。提前谢谢
根据@MRFrhn的建议,我做了一些改变
在我的action.js
adddispatch({type:MOVIE\u REQUEST\u THEATER})中代码>获取数据之前:
export const fetchDetail = ({ enCity, cnName }) => {
return (dispatch) => {
dispatch({ type: MOVIE_REQUEST_THEATER });
fetch(`https://obscure-reaches-65656.herokuapp.com/api/detail?city=${enCity}&movie=${cnName}`)
.then(response => response.json())
.then(responseData => {
dispatch({ type: MOVIE_DETAIL, payload: responseData[0].movie });
})
.catch((error) => console.log(error));
};
};
在我的示例中,添加一个案例:
case MOVIE_REQUEST_THEATER:
console.log('MOVIE_REQUEST_THEATER');
return {
...state,
loading: true, // show the spinner
};
我认为它应该会成功,因为在获取数据之前我返回了load
flagtrue
,但是当我看到我的日志,console.log('MOVIE\u REQUEST\u THEATER')时它就不起作用了代码>不显示。不知道为什么…当您第一次获取数据时,加载
是真的(从初始状态),当您得到响应时,您将其设置为假,但您从未将其再次设置为真,因此下次读取时它将为假。每次要提取时,必须将其设置为true。您可能还需要处理错误,例如当您的请求失败时,因此为了在redux中实现这一点,您需要为您的请求执行3个操作:
通知还原程序请求已开始的操作。还原程序可以通过在状态中切换isFetching
标志(或加载代码中的)来处理此操作。这样,UI就知道是时候显示微调器了。e、 g.动作类型MOVIELIST\u剧院请求
通知还原程序请求已成功完成的操作。还原程序可通过将新数据合并到其管理的状态并重置isFetching
来处理此操作。UI将隐藏微调器,并显示获取的数据。e、 g.动作类型MOVIELIST\u剧院\u成功
通知还原程序请求失败的操作。还原程序可以通过重置isFetching
来处理此操作。此外,一些还原程序可能希望存储错误消息,以便UI可以显示它。e、 g.动作类型MOVIELIST\u剧院\u故障
所以你的减速器看起来像这样:
case MOVIELIST_THEATER_REQUEST:
return {
...state,
loading: true, // this will show the spinner
error: false
};
case MOVIELIST_THEATER_SUCCESS:
return {
...state,
theaterList: action.payload,
loading: false,
error: false
};
case MOVIELIST_THEATER_FAILURE:
return {
...state,
loading: false,
error: true
};
...
阅读更多细节
============
更新:
将您的操作更改为:
export const fetchDetail = ({ enCity, cnName }) => {
return (dispatch) => {
dispatch(request_theater());
fetch(`https://obscure-reaches-65656.herokuapp.com/api/detail?city=${enCity}&movie=${cnName}`)
.then(response => response.json())
.then(responseData => {
dispatch({ type: MOVIE_DETAIL, payload: responseData[0].movie });
})
.catch((error) => console.log(error));
};
};
export function request_theater() {
return {
type: MOVIE_REQUEST_THEATER
}
}
当您第一次获取数据时,加载
为true(从初始状态),当您得到响应时,您将其设置为false,但您从未将其再次设置为true,因此下次读取时它将为false。每次要提取时,必须将其设置为true。您可能还需要处理错误,例如当您的请求失败时,因此为了在redux中实现这一点,您需要为您的请求执行3个操作:
通知还原程序请求已开始的操作。还原程序可以通过在状态中切换isFetching
标志(或加载代码中的)来处理此操作。这样,UI就知道是时候显示微调器了。e、 g.动作类型MOVIELIST\u剧院请求
通知还原程序请求已成功完成的操作。还原程序可通过将新数据合并到其管理的状态并重置isFetching
来处理此操作。UI将隐藏微调器,并显示获取的数据。e、 g.动作类型MOVIELIST\u剧院\u成功
通知还原程序请求失败的操作。还原程序可以通过重置isFetching
来处理此操作。此外,一些还原程序可能希望存储错误消息,以便UI可以显示它。e、 g.动作类型MOVIELIST\u剧院\u故障
所以你的减速器看起来像这样:
case MOVIELIST_THEATER_REQUEST:
return {
...state,
loading: true, // this will show the spinner
error: false
};
case MOVIELIST_THEATER_SUCCESS:
return {
...state,
theaterList: action.payload,
loading: false,
error: false
};
case MOVIELIST_THEATER_FAILURE:
return {
...state,
loading: false,
error: true
};
...
阅读更多细节
============
更新:
将您的操作更改为:
export const fetchDetail = ({ enCity, cnName }) => {
return (dispatch) => {
dispatch(request_theater());
fetch(`https://obscure-reaches-65656.herokuapp.com/api/detail?city=${enCity}&movie=${cnName}`)
.then(response => response.json())
.then(responseData => {
dispatch({ type: MOVIE_DETAIL, payload: responseData[0].movie });
})
.catch((error) => console.log(error));
};
};
export function request_theater() {
return {
type: MOVIE_REQUEST_THEATER
}
}
谢谢你的回复,我对你的代码有点困惑。事实上,我调用我的操作来获取数据并将其返回到我的reducer,每次都会成功。如果我的动作每次都成功,它将不会用于三个动作。提前谢谢。还是我应该改变一下我的行为?但是我找不到在哪里可以改变。在我的问题中,我已经更新了我的action.js
@徐博俊 你说得对,我正在编辑我的答案,以便更清楚@徐博俊 对于您的请求,您只使用一个操作,您需要实现我解释的3个操作。我建议阅读我在答案末尾的链接@徐博俊 我更新了我的答案。希望它能工作,如果不能,请告诉我。谢谢你的回复,我对你的代码有点困惑。事实上,我调用我的操作来获取数据并将其返回到我的reducer,每次都会成功。如果我的动作每次都成功,它将不会用于三个动作。提前谢谢。还是我应该改变一下我的行为?但是我找不到在哪里可以改变。在我的问题中,我已经更新了我的action.js
@徐博俊 你说得对,我正在编辑我的答案,以便更清楚@徐博俊 对于您的请求,您只使用一个操作,您需要实现我解释的3个操作。我建议阅读我在答案末尾的链接@徐博俊 我更新了我的答案。希望它能起作用,如果不行,请告诉我。