【问题标题】:React Redux server render but client side fetch dataReact Redux 服务器渲染但客户端获取数据
【发布时间】:2017-07-20 02:37:54
【问题描述】:

我正在我的一个演示反应应用程序上进行服务器渲染。尽管如果我刷新 url 上的页面以获取像 /doctor/:id 这样的医生,如果我在 /login 并尝试转到 /doctor/123456 ,但医生属性为空并且(this.props.doctor.name .first) 失败。

在这些情况下使用 redux 获取数据的好方法是什么?

代码如下

import { fetchDoctor } from '../../DoctorActions';
import { getDoctor } from '../../DoctorReducer';

class DoctorDetailPage extends Component {
    render() {
        return (
            <div>{this.props.doctor.name.first}</div>
        );
    }
}

DoctorDetailPage.need = [params => {
    return this.props.dispatch(fetchDoctor(params.id));
}];

function mapStateToProps(state, props) {
    return {
        doctor: getDoctor(state, props.params.id),
    };
}
DoctorDetailPage.propTypes = {
    doctor: PropTypes.shape({
        insurance: PropTypes.string,
        description: PropTypes.string,
        GUID: PropTypes.string,
        name: PropTypes.shape({
            first: PropTypes.string,
            last: PropTypes.string,
        })
    }),
    dispatch: PropTypes.func.isRequired,
};

export default connect(mapStateToProps)(DoctorDetailPage);

减速器

import { ADD_DOCTOR } from './DoctorActions';

// Initial State
const initialState = { list: [] };

const DoctorReducer = (state = initialState, action = {}) => {

    switch (action.type) {
        case ADD_DOCTOR:
            return {
                list: [action.doctor, ...state.list],
            };

        default:
            return state;
    }
};

export const getDoctor = (state, id) => {
  return state.doctors.list.filter(doctor => doctor._id === id)[0];
};

export default DoctorReducer;

动作

import callApi from '../../util/apiCaller';

// Export Constants
export const ADD_DOCTOR = 'ADD_DOCTOR';

// Export Actions
export function addDoctor(doctor) {
    return {
        type: ADD_DOCTOR,
        doctor,
    };
}

export function addDoctorRequest() {
    return () => {
        return true;
    };
}

export function fetchDoctor(id) {
    return (dispatch) => {
        return callApi(`doctors/${id}`)
            .then(res => dispatch(addDoctor(res)));
    };
}

日志错误

TypeError: Cannot read property 'name' of undefined

【问题讨论】:

  • 控制台显示的错误是什么?
  • “类型错误:无法读取未定义的属性‘名称’”,因为医生未定义。尽管服务器端正在工作,但在客户端获取失败
  • 您能否切换到“网络”选项卡并告诉我们 API 调用是否在客户端正确进行?
  • 不,不是。这就像在解析该对象之前尝试渲染。解决它的唯一方法是让 componentDidMount 函数和医生的 setState 清空。这种方式可以将其显示为空,然后将其替换为获取的数据。但这不是 redux 的做法

标签: reactjs redux react-router react-redux isomorphic-javascript


【解决方案1】:

一般来说,获取数据的好方法是什么?

一种用户友好的方法是进入页面/doctor/123456 而不需要有医生,这样用户就会得到即时反馈,表明他的操作(导航到第 x 页)有效。在 react-router 的 onEnter 方法或 componentDidMount 中,您应该启动一个操作 fetchDoctor 并同时向用户显示一个微调器或一条指示正在加载数据的消息。

render() {
    return (
        <div>
          { this.props.doctor && <div>{this.props.doctor.name.first}</div> }
          { ! this.props.doctor && <YourSpinnerComponent/> }
        </div>
    );
}

所以上面的渲染方法在加载数据时显示了一些东西,当数据进来时它显示它没有任何错误。

使用 redux 获取数据的好方法是什么?

处理异步操作的“古老”方式是使用redux-thunk。你可以阅读这个great SO answer about dispatching asynchronous redux actions

最新趋势是使用redux-saga。它是一个旨在使 React/Redux 应用程序中的副作用(即数据获取之类的异步操作和访问浏览器缓存之类的不纯操作)更容易和更好的库。 More about redux-saga.

因此,在您的情况下,您将创建一个 Saga 来处理获取。

More about redux-thunk vs redux-saga in this great SO answer.

【讨论】:

  • 感谢您的回答,效果很好。只是为了让其他用户知道,如果您将 return () 放在像 .. return (

    Hello!

    { this.props.doctor &&
    { this.props.doctor.name.first}
    }
    );
  • @PanagiotisVrs 感谢您的注意。我也更正了答案。
猜你喜欢
  • 1970-01-01
  • 2019-08-07
  • 2016-03-26
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 2018-01-05
  • 1970-01-01
相关资源
最近更新 更多