Search code examples
javascriptreactjsreduxreducersredux-promise

Parse XML in react-redux-promise app


The data source for my app only provides data in XML format.

I use axios to get the XML data. It ends up as a string in the data section of the result.

I have tried to use xml2js to convert it, but it just fires off a async job and returns, so I dont get the redux-promise middelware to work. The payload is nothing when the reducers sends the data to the component that should render it.

Not sure if this makes sense, but can I make the reducer wait for the new function call to return before sending the data on the the component?

action index.js

export function fetchData(jobid, dest) {
    const url = `${DATA_URL}jobid=${jobid}&refdist=${dest}`;
    const request = axios.get(url);

    console.log(request);

    return {
        type: FETCH_DATA,
        payload: request
    }
}

my reducer

export default function (state = [], action) {
    console.log(action);

    switch (action.type) {
        case FETCH_DATA:
            console.log("pre");
            parseString(action.payload.data, function (err, result) {
                // Do I need some magic here??? or somewhere else?
                console.dir(result);
            });

        return [action.payload.data, ...state];
    }
    return state;
}

Solution

  • you should change your action creator code, because axios is async. And dispatch action after receive data. You don't need this logic in reducer. For async actions you may use redux-thunk

    export const fetchData = (jobid, dest)=>dispatch =>{
        const url = `${DATA_URL}jobid=${jobid}&refdist=${dest}`;
    
        const request = axios.get(url).then(res=>{
            parseString(res, function (err, result) {
               if(result){
                    dispatch({
                       type: FETCH_DATA,
                       data:result
                    })
                }
                if(err) throw err
            });
        }).catch(err=>console.error(error))
    
    };
    ///clean reducer
    export default function (state = [], action) {
         switch (action.type) {
            case FETCH_DATA:
            return [...state, action.data ];
        }
        return state;
    }
    

    Also you may need to know about fetching process: loading, success , failure.Then action creator may looks like:

    export const fetchData = (jobid, dest)=>dispatch =>{
     const url = `${DATA_URL}jobid=${jobid}&refdist=${dest}`;
        dispatch({
           type: FETCH_DATA_REQUEST,
           data:result,
           isFetching:true
        })
        const request = axios.get(url).then(res=>{
            parseString(res, function (err, result) {
               if(result){
                    dispatch({
                       type: FETCH_DATA_SUCCESS,
                       data:result,
                       isFetching:false
                    })
                }
                if(err) throw err
            });
        }).catch(err=>{
            dispatch({
               type: FETCH_DATA_FAILURE,
               err:err,
               isFetching:false
            })
            console.error(error)
        })
    
    };