使用 redux 响应原生 axios api 调用

Posted

技术标签:

【中文标题】使用 redux 响应原生 axios api 调用【英文标题】:React native axios api calls with redux 【发布时间】:2019-10-02 21:13:02 【问题描述】:

我正在努力在 React Native 中使用 redux 和 axios 进行基本的 api 调用设置。

这是我的减速器 index.js

import  combineReducers  from 'redux'
import LibaryReducer from './LibraryReducer'
import ImportLibraryReducer from './ImportLibraryReducer'

let defaultState = 
    card: null



const mainReducer = (state = defaultState, action) => 
    if(action.type === "CHANGE_CARDS") 
        return 
            ...state,
            card: action.card
        
     else 
       return 
        ...state
       
    


export default mainReducer

这是我的操作 index.js

import axios from "axios"

export function loadCards()
    return(dispatch)=>
        return axios.get('http://localhost:4000/reports')
                .then(response => 
                    dispatch(changeCards(response.data))
                )
    


export function changeCards(cards) 
    return
        type: "CHANGE_CARDS",
        card: card
    

这是我的 app.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, Component from 'react';
import Platform, StyleSheet, Text, View from 'react-native';
import MainPage from './components/MainPage'
import  Header  from "native-base"

import Card from './components/Card'

import  Provider  from 'react-redux'
import  createStore, applyMiddleware  from 'redux'
import thunk from 'redux-thunk'

import reducers from './reducers'

const store = createStore(reducers, applyMiddleware(thunk))

type Props = ;
export default class App extends Component<Props> 
  render() 
    return (
      <Provider store=store>
        <View>
          <Header ><Text>hello</Text></Header>
          <Card />
        </View>
      </Provider>
    );
  

最后,这是我试图从 api 调用中检索数据的地方:

import React,  Component  from 'react';
import  Text, View  from 'react-native';
import Collapse,CollapseHeader, CollapseBody, AccordionList from 'accordion-collapse-react-native';
import  connect  from 'react-redux'
import * as actions from '../actions'

class Card extends Component 



  render() 

    const titleStyle = 
      backgroundColor: '#edeeef',
      fontWeight: "bold",
      color: '#454647',
      fontSize: 16,
      left: 8,
      fontFamily: 'Ionicons',
      top: 10
    

    const descMarkStyle = 
      left: 8,
      top: 4,
      fontFamily: 'Ionicons',
      color: '#454647',
      fontSize: 16
    

    console.log('in the render', this.props)

    return (
      <View>
          <Collapse >
              <CollapseHeader>
                <View
                  style=
                    backgroundColor: '#edeeef',
                    height: 38,
                    postion: 'absolute',
                    borderBottomWidth: .5,
                    borderBottomColor: '#black'
                   
                >
                  <Text style=titleStyle>
                   test
                  </Text>
                </View>

              </CollapseHeader>
              <CollapseBody>
                <Text style=descMarkStyle>test</Text>
                <Text style=descMarkStyle>test</Text>
              </CollapseBody>
            </Collapse>
      </View>
    );
  


function mapStateToProps(state) 
  return 
    state
   ;
 

 export default connect(mapStateToProps)(Card);

当我尝试在上面的组件中控制台记录 this.props 时,我得到卡的默认状态:null 而没有运行 api:https://imgur.com/a/acB40KU

我是 redux 的新手,我觉得我缺少一些明显的东西。

【问题讨论】:

您似乎没有在任何地方调用您的操作。 我应该在哪里调用它? 【参考方案1】:

您应该在Card 组件的componentDidMount 生命周期方法中触发您的操作。此外,您可以在导入和 connect 中解构您的操作。

import  loadCards  from '../actions'

class Card extends Component 

componentDidMount() 
  this.props.loadCards()

connect:

export default connect(mapStateToProps,  loadCards )(Card);

同样在changeCards 操作中:

card: cards

【讨论】:

【参考方案2】:

以下是如何通过 4 个步骤设置带有 redux 钩子和 react-native 的 axios:

源代码:https://github.com/trackmystories/Redux-hooks-counter-app-with-axios.

第 1 步:

创建一个actions.js文件:

actions.js

export const TOTAL_COUNT = "TOTAL_COUNT";

export const totalCount = (data) => (
  type: TOTAL_COUNT,
  data,
);

第 2 步:

定义和组合你的减速器:

reducer.js

import  combineReducers  from "redux";

import  TOTAL_COUNT  from "./actions";

let dataState =  data: [] ;

const total_counts = (state = dataState, action) => 
  switch (action.type) 
    case TOTAL_COUNT:
      return  ...state, data: action.data ;
    default:
      return state;
  
;

const counter = (state = 0, action) => 
  switch (action.type) 
    case "ADD":
      return state + 1;
    case "SUBTRACT":
      return state - 1;
    default:
      return state;
  
;

const rootReducer = combineReducers(
  counter,
  total_counts,
);

export default rootReducer;

第 3 步

创建一个 axios 获取请求并按照下面示例中的定义放置请求,然后分派和获取数据。

有了钩子,你不需要使用 connect mapStateToProps 和 dispatchStateToProps 和 redux 钩子,而是使用 useDispatch, useSelector 。

我们可以直接在按钮内部传递“ADD”和“SUBTRACT”操作,无需定义action.js文件。

CounterComponent.js

import React,  useEffect, useState  from "react";
import  StyleSheet, Text, View, ActivityIndicator  from "react-native";
import ActionButton from "./ActionButton";
import SubmitButton from "./SubmitButton";
import  useDispatch, useSelector  from "react-redux";
import axios from "axios";
import  totalCount  from "../actions";

export default function CounterComponent() 
  const dispatch = useDispatch();

  const [isFetching, setIsFetching] = useState(false);

  const total_counts = useSelector((state) => state.total_counts);
  const counter = useSelector((state) => state.counter);

  const  data  = total_counts;

  useEffect(() => getTotalCount(), []);

  const getTotalCount = () => 
    setIsFetching(true);

    let url = "https://url.firebaseio.com<name>.json";
    axios
      .get(url)
      .then((res) => res.data)
      .then((data) => dispatch(totalCount(data)))
      .catch((error) => alert(error.message))
      .finally(() => setIsFetching(false));
  ;

  const onSubmit = (counterState) => 
    let url = "https://url.firebaseio.com<name>.json";
    axios.put(url, counterState).then((response) => 
      console.log(response);
    );
  ;

  return (
    <View>

          <ActionButton
            onPress=() =>
              dispatch(
                type: "SUBTRACT",
              )
            
            title="subtract"
          />
         
   
       <View>  
        isFetching ? (
          <ActivityIndicator />
        ) : (
          <View>
            <Text>
              Current state:
              data.counter ? data.counter : counter
            </Text>
          </View>
        )
       </View>

          <ActionButton
            onPress=() =>
              dispatch(
                type: "ADD",
              )
            
            title="add"
          />

      
      <SubmitButton
        onPress=onSubmit(
          counterState: counter,
        )
        title="Submit"
      />
    </View>
  );

第 4 步:

最后将您的 RootReducer 链接到 createStore 并将其传递给 Provider。

import React from "react";
import  Text, View  from "react-native";
import  Provider  from "react-redux";
import  createStore  from "redux";
import CounterComponent from "./src/components/CounterComponent";
import rootReducer from "./src/reducer";

const store = createStore(rootReducer);

export default function App() 
  return (
    <View>
      <Text>Counter example with Redux Hooks and Axios</Text>
      <Provider store=store>
        <CounterComponent />
      </Provider>
    </View>
  );

【讨论】:

以上是关于使用 redux 响应原生 axios api 调用的主要内容,如果未能解决你的问题,请参考以下文章

使用 Axios 在 Redux 中处理 api 调用

无法使用 ReactJs、Axios、Redux 渲染/显示从 api 获取的数据

使用 axios 和 Redux Saga 调用 API 总是返回 undefined

将错误响应拦截器放在 redux-axios-middleware 上

如何在 redux 中使用 axios 库将数据发布到 API 服务器

与redux reducer结合的axios响应拦截器