简体   繁体   English

使用 React Hooks 和 Redux 获取数据

[英]Fetching Data using React Hooks and Redux

I'm currently trying to fetch data from my back end using the following.我目前正在尝试使用以下方法从后端获取数据。 I'm looking to destructure each event item to an eventIndexItem component, but events remains undefined after useEffect.我希望将每个事件项解构为一个 eventIndexItem 组件,但在 useEffect 之后事件仍未定义。

import React, { useState, useEffect } from 'react'
import EventIndexItem from './event_index_item'
import 'react-modern-calendar-datepicker/lib/DatePicker.css';
import { Calendar, utils } from 'react-modern-calendar-datepicker';

const EventIndex = ({ searchValue, fetchEvents }) => {
    let today = utils().getToday()
    const [ selectedDay, setSelectedDay ] = useState(today)

    function dateFormatter (selectedDay) {
        return selectedDay.month + " " + selectedDay.day
    }

    let formattedDate = dateFormatter(selectedDay)

    let events
    useEffect (() => {
        events = fetchEvents()
    }, [] )

    function handleEvents () {
        const filterEvents = events.filter(event => {
            let title = event.title
            if ( searchValue === "" || title.includes(searchValue) ) {
                return true
            } else {
                return false
            }
        })

        return filterEvents.map(event => (
            <EventIndexItem 
                key={event.id}
                event={event}
            />
        ))
    }


    return (

        <div className='event-index-container'>
            <div className='event-index-left'>
                <h1 className="event-index-date"> { formattedDate } </h1>
                { handleEvents() }
            </div>
            <div className='event-index-right'>
                <Calendar 
                    calendarClassName="event-index-calendar"
                    value={selectedDay}
                    onChange={setSelectedDay}
                    colorPrimary={'#00a2c7'}
                />
            </div>
        </div>
    )
}

export default EventIndex

Redux container looks like so. Redux 容器看起来像这样。

import { connect } from 'react-redux'
import EventIndex from './event_index'
import { fetchEvents } from '../../action/event_actions'

const msp = (state, ownProps) => {
    let searchValue = ownProps.searchValue
    return ({
        events: Object.values(state.entities.events),
        searchValue,
        currentUser: state.entities.users[state.session.id]
    })
}

const mdp = dispatch => {
    return ({
        fetchEvents: () => dispatch(fetchEvents())
    })
}

export default connect (msp, mdp) (EventIndex)

Action / Thunks动作 / Thunks

import * as EventAPIUtil from '../util/event_api_util';
import * as RSVPApiUtil from '../util/rsvp_api_util';

export const RECEIVE_EVENTS = "RECEIVE_EVENTS";
export const RECEIVE_EVENT = "RECEIVE_EVENT";
export const REMOVE_EVENT = "REMOVE_EVENT";

const receiveEvents = ( events ) => {
    return ({
        type: RECEIVE_EVENTS,
        events
    });
};

export const fetchEvents = () => (dispatch) => (
    EventAPIUtil.fetchEvents().then(events => dispatch(receiveEvents(events)))
);

Reducers减速机

import {
    RECEIVE_EVENTS,
    RECEIVE_EVENT,
    REMOVE_EVENT
} from '../action/event_actions';


const eventsReducer = (state = {}, action) => {
    Object.freeze(state);
    let newState;
    switch (action.type) {
        case RECEIVE_EVENTS:
            return action.events;
        case RECEIVE_EVENT:
            newState = Object.assign({}, state, { [action.event.id]: action.event });
            return newState;
        case REMOVE_EVENT:
            newState = Object.assign({}, state)
            delete newState[action.eventId]
            return newState;
        default:
            return state;
    }
};

export default eventsReducer; 

I've previously created a class component calling this.props.fetchEvents() in componentDidMount and then invoking my handleEvents() in render with no issue.我之前创建了一个 class 组件,在componentDidMount中调用this.props.fetchEvents() ,然后在渲染中调用我的handleEvents()没有问题。 However, the variable events is undefined, but I do see events being added to redux state via redux-logger.但是,变量 events 是未定义的,但我确实看到通过 redux-logger 添加到 redux state 的事件。 Please advise.请指教。 Also feel free to critique current code as well.也可以随意批评当前的代码。

There are two approaches to this problem.这个问题有两种方法。 You can either:您可以:

  • Fetch from React component (don't recommend)从 React 组件中获取(不推荐)

To do so you will need to do some refactoring to your code为此,您需要对代码进行一些重构

  1. All API call functions should be wrapped in a Promise.所有 API 调用函数都应包装在 Promise 中。
  2. You'll have to add the results to the Redux state through an action dispatch您必须通过操作调度将结果添加到 Redux state
  3. You'll use async callback function in useEffect您将在 useEffect 中使用异步回调useEffect
  4. You'll need to wrap the fetch in a conditional to check if values already exist in the state.您需要将提取包装在条件中以检查 state 中是否已存在值。

Why I don't recommend:为什么我不推荐:

Because you are mixing between business state and UI state.因为您在业务 state 和 UI state 之间混合。 Redux helps separate this by managing the business state in Redux and the UI state in React. Redux 通过管理 Redux 中的业务 state 和 ReactA6 中的 UI Z9ED39E2EA931586B6AEZEFA7 来帮助区分这一点。 So always try avoiding mixing them.所以总是尽量避免混合它们。

  • Dispatch an async action from Redux (recommended)从 Redux 调度异步操作(推荐)
    1. Use Redux thunk for async actions.使用 Redux thunk 进行异步操作。
    2. dispatch the action from useEffectuseEffect调度操作
    3. make the API call from the reducer.从 reducer 调用 API。
    4. make your conditions in the reducer before the call.在调用之前在减速器中制作您的条件。

Note that you must set conditions to make the API call and update the state or else the React component will keep re-rendering.请注意,您必须设置条件以进行 API 调用并更新 state 否则 React 组件将继续重新渲染。

Why I recommend:为什么我推荐:

It separates business state from UI state.它将业务 state 与 UI state 分开。

  • One way for implementation of the recommended approach.实施推荐方法的一种方法。

createSlice For auto-generating action creators, Reducer and selectors. createSlice用于自动生成动作创建者、Reducer 和选择器。

createAsyncThunk For working with API in Redux. createAsyncThunk用于在 Redux 中使用 API。

React Redux template Offical template, use as a setup example. React Redux template官方模板,用作设置示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM