使用 redux 响应本机 axios api 调用

React native axios api calls with redux

我正在努力在 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 时,我得到了 card: null 的默认状态,没有 api 运行: https://imgur.com/a/acB40KU

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

您应该在 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

以下是如何通过 4 个步骤设置带有 redux hooks 和 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 get 请求并按照下面示例中的定义发出请求,然后分派和获取数据。

有了钩子,你不需要使用 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 步:

最后 link 你的 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>
  );
}