【问题标题】:Redux - Fetch data, but render in another componentRedux - 获取数据,但在另一个组件中呈现
【发布时间】:2020-11-18 11:56:07
【问题描述】:

我目前正在 Component1 中获取数据,然后调度一个操作以使用响应更新存储。数据可以在this.props的Component2中看到,但是返回响应时如何渲染呢?当数据返回时,我需要一种方法来重新加载组件。

最初我在componentDidMount 中运行了一系列函数,但这些函数都是在数据从 Component1 返回到 Redux 存储之前执行的。组件之间是否存在某种async/await 样式?

class Component1 extends React.Component {
    componentDidMount() {
        this.retrieveData()
    }

    retrieveData = async () => {
        let res = await axios.get('url')
        updateParam(res.data) // Redux action creator
    }
}
class Component2 extends React.Component {
    componentDidMount() {
       this.sortData()
    }

    sortData = props => {
        const { param } = this.props
        let result = param.sort((a,b) => a - b)
    }
}

mapStateToProps = state => {
    return { param: state.param }
}

connect(mapStateToProps)(Component2)

在 Component2 中,this.props 最初是未定义的,因为尚未返回数据。当它被返回时,尽管this.props 被填充了数据,组件也不会重新渲染。

【问题讨论】:

  • 数据准备好后渲染组件reactjs.org/docs/conditional-rendering.html
  • 组件在 state 或 props 更新时重新渲染。如果 Component2 接收到一个新的 prop 对象,那么它应该重新渲染。如果你做了一些有点傻的事情,比如将 props 存储到本地组件状态,那么你需要使用 componentDidUpdate 或具有适当依赖关系的 useEffect 来更新本地状态。请使用Minimal, Complete, and Reproducible 代码示例更新您的问题以获得更多帮助或更好的帮助。
  • 我已经用一些代码更新了这个问题。
  • "...但是视图总是落后一个渲染。"你在用 sortData 函数中的 result 做什么?
  • appointmentDates 应该是一个本地组件状态对象,然后当您在生命周期函数中更新它时,react 将正确重新呈现,您无需强制执行任何操作。 OR 因为您除了计算要渲染的格式化数据之外什么都不做,Appointments 应该只在渲染函数中调用setAppointmentDatessortAppointmentsByDate。跨度>

标签: reactjs redux redux-thunk


【解决方案1】:

假设 updateParam 动作创建者在 mapDispatchToProps 中的 mapDispatchToProps 中正确包装了对 dispatch 的调用,connect HOC AND 从 @987654325 中的道具正确访问@,那么我建议检查/比较 componentDidUpdate 中以前的 props 并调用 sortData 如果特别是 param 的 prop 值更新。

class Component2 extends React.Component {
    componentDidMount() {
       this.sortData()
    }

    componentDidUpdate(prevProps) {
      const { param } = this.props;
      if (prevProps.param !== param) { // <-- if param prop updated, sort
        this.sortData();
      }
    }

    sortData = () => {
        const { param } = this.props
        let result = param.sort((a, b) => a - b));
        // do something with result
    }
}

mapStateToProps = state => ({
  param: state.param,
});

connect(mapStateToProps)(Component2);

编辑

来自存储库的给定组件代码

let appointmentDates: object = {};
class Appointments extends React.Component<ApptProps> {
    componentDidUpdate(prevProps: any) {
        if (prevProps.apptList !== this.props.apptList) {
            appointmentDates = {};
            this.setAppointmentDates();
            this.sortAppointmentsByDate();
            this.forceUpdate();
        }
    }

    setAppointmentDates = () => {
        const { date } = this.props;
        for (let i = 0; i < 5; i++) {
            const d = new Date(
                new Date(date).setDate(new Date(date).getDate() + i)
            );
            let month = new Date(d).toLocaleString("default", {
                month: "long"
            });
            let dateOfMonth = new Date(d).getDate();
            let dayOfWeek = new Date(d).toLocaleString("default", {
                weekday: "short"
            });
            // @ts-ignore
            appointmentDates[dayOfWeek + ". " + month + " " + dateOfMonth] = [];
        }
    };

    sortAppointmentsByDate = () => {
        const { apptList } = this.props;
        let dates: string[] = [];
        dates = Object.keys(appointmentDates);
        apptList.map((appt: AppointmentQuery) => {
            return dates.map(date => {
                if (
                    new Date(appt.appointmentTime).getDate().toString() ===
                    // @ts-ignore
                    date.match(/\d+/)[0]
                ) {
                    // @ts-ignore
                    appointmentDates[date].push(appt);
                }
                return null;
            });
        });
    };

    render() {
        let list: any = appointmentDates;

        return (
            <section id="appointmentContainer">
                {Object.keys(appointmentDates).map(date => {
                    return (
                        <div className="appointmentDateColumn" key={date}>
                            <span className="appointmentDate">{date}</span>
                            {list[date].map(
                                (apptInfo: AppointmentQuery, i: number) => {
                                    return (
                                        <AppointmentCard
                                            key={i}
                                            apptInfo={apptInfo}
                                        />
                                    );
                                }
                            )}
                        </div>
                    );
                })}
            </section>
        );
    }
}

appointmentDates 应该是一个本地组件状态对象,然后当您在生命周期函数中更新它时,react 将正确重新呈现,您无需强制执行任何操作。 因为您除了计算要渲染的格式化数据之外什么都不做,Appointments 应该只在渲染函数中调用 setAppointmentDatessortAppointmentsByDate。 p>

【讨论】:

  • 与 StackQ 的回答类似,我必须在 componentDidUpdate 的末尾添加 this.forceUpdate 才能正常工作。我正在比较道具中的大物体。即使我要单独比较每个属性,有些被初始化为 [ ][ ] === [ ] 是错误的。这会导致componentDidUpdate 无意中执行。
  • @SimonWong 是的,非常相似。直到我回答并刷新页面后,我才看到他们的。也许您可以更新您的问题以包含 complete 组件代码并分享您正在比较的道具形状。我们的答案模式是正确的,但似乎问题在于条件测试是否正确。
猜你喜欢
  • 1970-01-01
  • 2018-05-05
  • 2016-07-24
  • 1970-01-01
  • 2017-07-11
  • 2017-08-27
  • 1970-01-01
  • 2021-02-23
  • 2018-05-01
相关资源
最近更新 更多