Redux 状态加载,但反应不渲染
Posted
技术标签:
【中文标题】Redux 状态加载,但反应不渲染【英文标题】:Redux state loading, but react not rending 【发布时间】:2021-01-17 17:33:42 【问题描述】:所以我从服务器端获取数据。状态在 redux 中加载,但 react 没有渲染处于状态的数组。
这是我的 react 组件:
import React, useEffect, useState from "react";
import IonContent, IonButton, IonButtons, IonToolbar, IonTitle, IonHeader, IonList from "@ionic/react";
import IInviteModal, IInviteReduxProps from "../types/interfaces";
import connect from "react-redux";
import getInvites from '../flux/actions/eventActions';
import InviteListItem from "./InviteListItem";
const InviteModal = ( getInvites, invite, onDismissModal: IInviteModal) =>
// const [invites, setInvites] = useState();
useEffect(() =>
getInvites();
, [getInvites]);
// const invites = invite;
const invites = ...invite
const handleOnSubmit = (e: any) =>
e.preventDefault();
;
return (
<IonContent>
<form onSubmit=handleOnSubmit>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonButton
onClick=onDismissModal
>
Back
</IonButton>
</IonButtons>
<IonTitle>
<div className="ion-text-center">
Event Invites
</div>
</IonTitle>
</IonToolbar>
</IonHeader>
<IonList>
invites ?
invites.map(invite => <InviteListItem
invite=invite
key=invite._id
/>
)
: "Loading..."
</IonList>
</form>
</IonContent>
);
;
const mapStateToProps = (state: IInviteReduxProps) => (
invite: state.invite
);
export default connect(mapStateToProps, getInvites )(InviteModal);
import React from 'react';
import IonItem, IonLabel, IonButton, IonGrid, IonRow, IonCol from '@ionic/react';
import connect from 'react-redux';
import setCurrentI from '../flux/actions/eventActions';
import IInviteListItem from '../types/interfaces';
import format from "date-fns";
const InviteListItem = ( invite, setCurrentI : IInviteListItem) =>
const setCurrentInvite = (invite: any) => setCurrentI(invite);
return (
<div>
<IonItem
onClick=() => setCurrentInvite(invite)
>
<IonLabel>
<h2>invite.title</h2>
<p>invite.location</p>
<br />
<p>format(new Date(invite.dateStart), "MMM d', 'h:mm aaa")—
format(new Date(invite.dateEnd), "MMM d', 'h:mm aaa")</p>
/* <br /> */
<div className="ion-text-center">
<IonGrid>
<IonRow>
<IonCol>
<IonButton size="small" fill="clear">
Accept
</IonButton>
</IonCol>
<IonCol>
<IonButton size="small" fill="clear">
_
</IonButton>
</IonCol>
<IonCol>
<IonButton size="small" fill="clear">
Decline
</IonButton>
</IonCol>
</IonRow>
</IonGrid>
</div>
</IonLabel>
</IonItem>
</div>
);
;
export default connect(null, setCurrentI)(InviteListItem);
这是减速器:
import GET_EVENTS, GET_EVENT, ADD_EVENT, DELETE_EVENT, EVENTS_LOADING, UPDATE_EVENT, SET_CURRENT, CLEAR_CURRENT, LOG_ARRIVAL, EVENT_ERROR, GET_INVITES from '../actions/types';
import IAction, IEvent, IInvite from '../../types/interfaces';
const initialState =
events: [],
invites: [],
current: [],
loading: false
;
interface IState
events: IEvent[];
invites: IInvite[];
export default function(state: IState=initialState, action: IAction)
switch(action.type)
case GET_EVENTS:
return
...state,
events: action.payload,
loading: false
;
case GET_INVITES:
return
...state,
invites: action.payload,
loading: false
;
Page not mapping array, state is loaded Diff redux output
页面只显示“正在加载...”
奇怪的是,我使用完全相同的结构来获取其他数据和数组映射而没有问题。
关于如何让数组渲染的任何想法?
这是有效的代码:
import React, useEffect from 'react';
import IonContent, IonLabel, IonList from '@ionic/react';
import connect from 'react-redux';
import getEvents from '../flux/actions/eventActions';
import IEventReduxProps, ICalendar from '../types/interfaces';
import EventListItem from './EventListItem';
const Calendar = ( getEvents, event : ICalendar) =>
useEffect(() =>
getEvents();
, [getEvents]);
const events = event;
return (
<IonContent>
<IonList>
events.map(event => <EventListItem
event=event
key=event._id/>
)
</IonList>
</IonContent>
);
;
const mapStateToProps = (state: IEventReduxProps) => (
event: state.event
);
export default connect(mapStateToProps, getEvents )(Calendar);
import React from 'react';
import IonItem, IonIcon, IonLabel, IonButton from '@ionic/react';
import connect from 'react-redux';
import deleteEvent, setCurrent from '../flux/actions/eventActions';
import IEventListItem from '../types/interfaces';
import closeCircle from 'ionicons/icons';
import format from "date-fns";
const EventListItem = ( event, deleteEvent, setCurrent : IEventListItem) =>
const handleDelete = (_id: string) => deleteEvent(_id);;
const setCurrentEvent = (event: any) => setCurrent(event);;
return (
<div>
<IonItem
onClick=() => setCurrentEvent(event)
// routerLink=`/event/$event._id`
>
<IonLabel>
<h2>event.title</h2>
<p>event.location</p>
<p>format(new Date(event.dateStart), "MMM d', 'h:mm aaa")—
format(new Date(event.dateEnd), "MMM d', 'h:mm aaa")</p>
/* MAP the ATTENDEES */
event.attendees.map((attendee, _id)=> (
<p key=attendee._id >
attendee.name
/* attendee.email */
</p>
)
)
</IonLabel>
<IonButton
routerLink=`/event/log/$event._id`
color="success"
fill="clear"
>Log</IonButton>
<IonButton
routerLink=`/event/$event._id`
fill="clear"
>Edit</IonButton>
<IonIcon
icon=closeCircle
slot="end"
className="remove-btn"
color="danger"
onClick=() => handleDelete(event._id)
/>
</IonItem>
</div>
);
;
export default connect(null, deleteEvent, setCurrent )(EventListItem);
【问题讨论】:
您能否为getInvites
提供reducer 并使用redux 开发工具(标签差异)进行截图?
是 getInvites
一个已经绑定到你的 redux store 的函数吗?尝试用connect(mapStateToProps, dispatch => bindActionCreators( getInvites ))(InviteModal);
替换connect(mapStateToProps, getInvites )(InviteModal);
@KirillSkomarovskiy 完成,我还添加了可以正常工作的代码。
@JacobSmit 在尝试您的 getInvites 解决方案时出错:“未提供 'dispatch' 的参数”
抱歉,我离开了一个星期。 bindActionCreators( getInvites )
应该包含 dispatch 作为第二个参数 bindActionCreators( getInvites , dispatch)
。
【参考方案1】:
如果redux store
中有数据,则必须从react-redux
添加useSelector()
。
这样,当新的props
进入应用程序时,您将通知组件,这将导致组件向re-render
发送新数据。
还有一个问题是你同时使用import connect from "react-redux";
和hooks
。
您必须决定是要将redux
与hooks
一起使用还是class
。
如果你想将它与钩子一起使用,那么你需要:useSelector
,useActions
。
如果你想将它与类组件一起使用,那么你需要来自 redux:mapStateToProps
、mapDispatchToProps
、connect
。
简而言之:您正在混合两种不同的方法。
【讨论】:
【参考方案2】:我想你在connect
上遇到了一些问题。 HOC connect 有 4 个参数。一个特别的options
我没有发现你的问题。你能试试下面的两个组件吗?
如果这段代码没有帮助 - 我认为你的问题在于减速器、动作、中间件。
InviteModal.tsx
import React from 'react';
import useSelector, useDispatch from 'react-redux';
import IonContent, IonButton, IonButtons, IonToolbar, IonTitle, IonHeader, IonList from '@ionic/react';
import getInvites from '../flux/actions/eventActions';
import IInviteModal, IInviteReduxProps from '../types/interfaces';
import InviteListItem from './InviteListItem';
/* TODO: make correct IInviteModal */
const InviteModal: React.FC<IInviteModal> = ( onDismissModal ) =>
const dispatch = useDispatch();
const invites = useSelector(( invite : IInviteReduxProps) => invite);
React.useEffect(() =>
dispatch(getInvites());
, [dispatch]);
const handleOnSubmit = React.useCallback((e: any) =>
e.preventDefault();
, []);
return (
<IonContent>
<form onSubmit=handleOnSubmit>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonButton onClick=onDismissModal>
Back
</IonButton>
</IonButtons>
<IonTitle>
<div className="ion-text-center">
Event Invites
</div>
</IonTitle>
</IonToolbar>
</IonHeader>
<IonList>
invites
? invites.map(invite => <InviteListItem invite=invite key=invite._id />)
: "Loading..."
</IonList>
</form>
</IonContent>
);
;
export default InviteModal;
InviteListItem.tsx
import React from 'react';
import IonItem, IonLabel, IonButton, IonGrid, IonRow, IonCol from '@ionic/react';
import useDispatch from 'react-redux';
import format from 'date-fns';
import setCurrentI from '../flux/actions/eventActions';
import IInviteListItem from '../types/interfaces';
const formatData = (data: string) => format(new Date(data), "MMM d', 'h:mm aaa");
/* TODO: make correct IInviteListItem */
const InviteListItem: React.FC<IInviteListItem> = ( invite ) =>
const dispatch = useDispatch();
const setCurrentInvite = React.useCallback(() =>
dispatch(setCurrentI(invite));
, [invite, dispatch]);
return (
<IonItem onClick=setCurrentInvite>
<IonLabel>
<h2>invite.title</h2>
<p>invite.location</p>
<br />
<p>
formatData(invite.dateStart)
—
formatData(invite.dateEnd)
</p>
<div className="ion-text-center">
<IonGrid>
<IonRow>
<IonCol>
<IonButton size="small" fill="clear">
Accept
</IonButton>
</IonCol>
<IonCol>
<IonButton size="small" fill="clear">
_
</IonButton>
</IonCol>
<IonCol>
<IonButton size="small" fill="clear">
Decline
</IonButton>
</IonCol>
</IonRow>
</IonGrid>
</div>
</IonLabel>
</IonItem>
);
;
export default InviteListItem;
【讨论】:
这会在我正在渲染的主页上引发各种错误。 @morethan1 你能提供屏幕或文字吗? 你是对的,这与我的减速器有关。我为 Invites 创建了单独的减速器和操作,现在一切正常。谢谢以上是关于Redux 状态加载,但反应不渲染的主要内容,如果未能解决你的问题,请参考以下文章