Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
57
rated 0 times [  64] [ 7]  / answers: 1 / hits: 20485  / 8 Years ago, mon, may 16, 2016, 12:00:00

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


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



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;
}


With action:



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

return {
type: FETCH_BOOKS,
payload: request
}
}


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



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


The api returns the following structured JSON:



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


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
}
};


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


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.


More From » reactjs

 Answers
5

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).



Regarding the technical solution:



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.)



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.



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 is supposed to do the date transformation from backend format to frontend format.



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
};
}


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



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);


and then pass your reducers function to this store.



Please keep asking if you have any further questions.


[#62155] Friday, May 13, 2016, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
yulisa

Total Points: 436
Total Questions: 102
Total Answers: 123

Location: Palau
Member since Tue, May 30, 2023
1 Year ago
;