我使用react-redux
创建了一个项目,我的项目有很多城市,点击每个城市都会导航到我的班级组件TheaterList.js
我设置我的reducer有一个loading
标记(当获取数据成功时默认为true
然后使用false
返回它)我的操作MOVIELIST_THEATER
,这是我的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);
一开始效果很好,就像显示<Spinner />
等待数据返回并重新呈现状态然后显示我的<FlatList />
,但当我回到屏幕并导航到{{1再次,我发现TheaterList.js
值仍为this.props.loading
。这会导致false
无法显示。
我尝试控制加载标记,在<Spinner />
函数下添加this.props.loading = true;
。显然这是不对的。
这是我的componentDidMount()
:
action.js
那么,如果使用相同的类组件,如何将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));
};
};
标志与loading
完全一致?
任何帮助将不胜感激。提前谢谢。
根据@MRFrhn的建议,我做了一些改变。
在我的react-redux
添加action.js
之前获取数据:
dispatch({ type: MOVIE_REQUEST_THEATER });
在我的reducer中添加一个案例:
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
};
标记loading
,但它没有用,然后我看到我的日志,true
没有显示出。不知道为什么......
答案 0 :(得分:1)
当您第一次获取数据时,loading
为真(从初始状态开始),当您收到回复时,将其设置为 false ,但您从未将其设置为true再次,所以下次你读它时会是假的。每次要获取时,都必须将其设置为 true 。您可能还需要处理错误,例如当您的请求失败时,因此在redux中以正确的方式实现此错误,您需要针对您的请求执行3个操作:
isFetching
标志(或代码中的loading
)来处理此操作。这样UI就知道是时候展示一个微调器了。例如操作类型MOVIELIST_THEATER_REQUEST
isFetching
来处理此操作。 UI将隐藏微调器,并显示获取的数据。例如操作类型MOVIELIST_THEATER_SUCCESS
isFetching
来处理此操作。此外,某些Reducer可能希望存储错误消息,以便UI可以显示它。例如操作类型MOVIELIST_THEATER_FAILURE
所以你的减速器看起来像这样:
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
};
...
阅读this了解详情。
============
更新
将您的操作更改为:
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
}
}