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
add
dispatch({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
flag
true
,但是当我看到我的日志,
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个操作。我建议阅读我在答案末尾的链接@徐博俊 我更新了我的答案。希望它能起作用,如果不行,请告诉我。