使用Redux反应本地axios API调用

时间:2019-05-15 16:51:23

标签: reactjs react-native redux axios redux-thunk

我正在努力在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的新手,我觉得我显然缺少一些东西。

2 个答案:

答案 0 :(得分:1)

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

import { loadCards } from '../actions'

class Card extends Component {

componentDidMount() {
  this.props.loadCards()
}

connect中:

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

也在changeCards动作中:

card: cards

答案 1 :(得分:0)

以下是如何通过 4 个步骤使用 redux hooks 和 react-native 设置 axios:

源代码:here

第 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 get 请求和 put 请求,如下面的示例中定义的那样,然后分派和获取数据。

对于钩子,您不需要使用带有 redux 钩子的连接 mapStateToProps 和 dispatchStateToProps 而是使用 { 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>
  );
}