在达到状态之前在 Redux Reducer 中格式化日期 [英] Format date in Redux Reducer before it hits state

查看:38
本文介绍了在达到状态之前在 Redux Reducer 中格式化日期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从标准 JS 日期对象格式化日期,该对象来自服务器并通过 Redux 通过 REST api 输入 React,其初始输出为:

how can I format a date from a standard JS date object, which has come from the server and is fed into React via Redux through a REST api, which has an initial output of:

"2016-05-16T13:07:00.000Z"

转换成不同的格式?所以它被列为DD MM YYYY?

Into a different format? So it is listed as DD MM YYYY?

我可以在Reducer of Action中通过操作请求结果或payload来做到这一点吗:

Can I do this in the Reducer of Action by manipulating the request result, or the payload:

import { FETCH_BOOKS, FETCH_BOOK } from '../actions';

const INITIAL_STATE = { books: [], book: null };

export default function(state = INITIAL_STATE, action) {
    switch(action.type) {
        case FETCH_BOOK:
            return { ...state, book: action.payload.data };
        case FETCH_BOOKS:
            return { ...state, books: action.payload.data };
    }
    return state;
}

有行动:

export function fetchBooks() {
    const request = axios.get('/api/books');

    return {
        type: FETCH_BOOKS,
        payload: request
    }
}

fetchBooks() 在 Books React 组件的 componentWillMount() 方法中调用:

fetchBooks() is called in the componentWillMount() method of the Books React component:

componentWillMount() {
    this.props.fetchBooks();
}

api 返回以下结构化 JSON:

The api returns the following structured JSON:

[{"_id":0,"date":"2016-05-16T13:07:00.000Z","title":"Eloquent JavaScript","description":"Learn JavaScript"}]

更新

非常感谢 Nicole 和 nrabinowitz - 我已经在动作创建器中实现了以下更改...

Update

Thank you very much Nicole and nrabinowitz - I have implemented the following changes... in the action creators

function transformDateFormat(json) {
    const book = {
        ...json,
        id: json.data._id,
        // date: new Date(moment(json.data.date).format('yyyy-MM-dd'))
        date: new Date(json.data.date)
    }
    console.log(book);
    return book;
}

export function fetchBook(id) {
    const request = axios.get(`/api/books/${id}`)
        .then(transformDateFormat);

    return {
        type: FETCH_BOOK,
        payload: request 
    }
};

我在转换日期函数中记录 book 对象,并将 iddate 添加到对象的根,但实际上 json 的结构必须是 book.data.idbook.data.date.我不确定如何在 transformDate 函数中创建正确的结构以返回给动作创建者.

I am logging the book object in the transform date function, and it is adding id and date to the root of the object, but the structure of the json actually needs to be book.data.id and book.data.date. I'm not sure how to create the correct structure within the transformDate function to return to the action creator.

这是转换日期函数控制台日志中的书对象:

This is the book object from the transform date function console log:

Object {data: Object, status: 200, statusText: "OK", headers: Object, config: Object…}
config: Object
data: Object
    __v:0
    _id: "5749f1e0c373602b0e000001"
    date: "2016-05-28T00:00:00.000Z"
    name:"Eloquent JavaScript"
    __proto__:Object
date: Sat May 28 2016 01:00:00 GMT+0100 (BST)
headers: Object
id: "5749f1e0c373602b0e000001"
request: XMLHttpRequest
status: 200
statusText: "OK"
__proto__: Object

我的函数需要将 id 和 date 放在数据对象中.(日期只是标准日期格式,因为我的 moment 实现出了问题 (date: new Date(moment(json.data.date).format('yyyy-MM-dd'))返回无效日期).

My function needs to place the id and date inside the data object. (The date is just standard date format as something is wrong with my implementation of moment (date: new Date(moment(json.data.date).format('yyyy-MM-dd')) returns Invalid date).

再次感谢您的帮助 - 非常感谢.

Thanks again for all your help - really appreciated.

推荐答案

当数据到达前端时,即在您的 AJAX 请求中,我会立即执行此转换.这样,您的前端应用程序只会处理您希望它们成形的数据,并且您的请求处理程序封装并隐藏服务器提供的数据结构,并将数据以所需的形状传递给前端应用程序.

I would do this transformation immediately when the data arrives in the frontend, i.e. in your AJAX request. This way, your frontend application only works with the data as you intend them to be shaped, and your request handler encapsulates and hides the data structures as they are provided from the server and passes the data to the frontend application in the desired shape.

(在领域驱动设计中,这被称为反腐败层").

(In Domain-Driven Design, this goes under the name of "Anticorruption Layer").

关于技术方案:

目前,您的事件负载包含对数据的承诺.您没有向我们展示您调用 fetchBooks() 的位置,即执行 Promise 的位置.这就是您需要进行数据转换的地方.(但就我个人而言,我更愿意将数据转换保留在 fetchBooks 函数中.)

Currently, your event payload contains a promise to the data. You don't show us where you invoke fetchBooks(), i.e. where the promise is executed. That's where you need to do the data transformation. (But personally, I'd rather keep the data transformation inside the fetchBooks function.)

此外,这也是您需要将数据发送到 redux 存储的地方.为了能够异步减少事件,你需要类似 redux-thunk 的东西.

Also, that's the point where you need to send the data to the redux store. To be able to reduce events asynchronously, you need something like redux-thunk.

解决方案可能看起来像这样(抱歉,我在使用 Promise 方面不是很有经验,所以我将在这里使用回调,但也许您可以以某种方式将其转换为 Promise):

A solution might look like this (my apologies, I'm not very experienced in using promises, so I'll use a callback here, but maybe you can somehow translate that to a promise):

export function fetchBooks(callback) {
    const request = axios.get('/api/books')
                    .then(function (response) {
                       callback(transformData(response));
                    });
}

transformData 应该是做后端格式到前端格式的日期转换.

transformData is supposed to do the date transformation from backend format to frontend format.

在其他地方,您可能会触发一个动作,该动作被发出以获取书籍(我们暂时将其称为 loadBooks).这就是您需要进行异步分派的地方:

Somewhere else you probably trigger an action that gets emitted in order to fetch the books (let's call it loadBooks for now). That's where you need to do the asynchronous dispatch:

function loadBooks() {
    return (dispatch, getState) => {

        fetchBooks(response => {
            dispatch(receiveBooks(response));
        });
    };
}

function receiveBooks(data) {
    return {
        type: FETCH_BOOKS,
        payload: data
    };
}

这样,您只会将数据从 AJAX 调用实际返回后分派到 redux 存储.

This way, you will only dispatch the data to the redux store once it was actually returned from the AJAX call.

要使用 redux-thunk,你需要像这样将它的中间件注入你的商店:

To use redux-thunk, you need to inject its middleware into your store like this:

import thunkMiddleware from "redux-thunk";
import { createStore, applyMiddleware } from "redux";

const createStoreWithMiddleware = applyMiddleware(
    thunkMiddleware
)(createStore);

然后将你的 reducers 函数传递给这个 store.

and then pass your reducers function to this store.

如果您还有其他问题,请继续提问.

Please keep asking if you have any further questions.

这篇关于在达到状态之前在 Redux Reducer 中格式化日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆