aditya kumar
aditya kumar

Reputation: 3023

How to do two type of filtering from same redux state in reactjs

I have a react js app which uses redux for state management. It has list of message which is displayed on screen. And two dropdown which filters the list according to product message and order message. Whole message list is coming from redux state.

I tried doing this but I ran into problem that once I filter the list next time it tries to run filter from filtered list and result is I get no message there.

I am not sure if this is the right way to do this.

reducers.js

const initialState = {
    loading: false,
    loaded: false,
    messageList: [],     <---- I am displaying this messageList in my component.
    fetchError: null,
}

export default (state=initialState, action) => {
    switch (action.type) {
        case GET_MESSAGE_LIST_LOAD:
            return {
                ...state,
                loading: true
            };
        case GET_MESSAGE_LIST_SUCCESS:
            return {
                ...state,
                loading: false,
                loaded: true,
                messageList: action.payload,
            };

        case FILTER_MESSAGE_BY_ORDER:
            return {
                ...state,
                filterState: action.payload,
                messageList: state.messageList.filter((item)=> {
                    return  item.productId === null;
                })
            };
        case FILTER_MESSAGE_BY_PRODUCT:
            return {
                ...state,
                filterState: action.payload,
                messageList: state.messageList.filter((item) => {
                    return item.orderNumber === null;
                })
            };
        case GET_MESSAGE_LIST_ERROR:
            return {
                ...state,
                loaded: false,
                fetchError: action.error,
            };
        default:
            return {
                ...state
            };
    }
}

action.js

export const getMessageList = () => dispatch => {
    dispatch({
        type: GET_MESSAGE_LIST_LOAD
    });
    new _rest().get('message/list')
        .then(res => {
            // console.log('messageList',res)
            dispatch({
                type: GET_MESSAGE_LIST_SUCCESS,
                payload: res.data._embedded.messageListResourceList
            })

        }).catch(err => {
            dispatch({
                type: GET_MESSAGE_LIST_ERROR,
                error: err
            })
    })
}

export const filterOrderMessage = () => dispatch => {

    dispatch({
        type: FILTER_MESSAGE_BY_ORDER
    })

}

export const filterProductMessage = () => dispatch => {

    dispatch({
        type: FILTER_MESSAGE_BY_PRODUCT
    })

}

This is how my UI Looks like It has dropdown at the top which has to options to filter ORDER MESSAGE and PRODUCT MESSAGE.

Image

Upvotes: 0

Views: 139

Answers (3)

gdh
gdh

Reputation: 13702

You are mutating the messageList. Instead, have a separate state for filtered messages in the store. In your component, make sure to render based on filteredMessageList.

Code Sample

const initialState = {
    loading: false,
    loaded: false,
    messageList: [],
    filteredMessageList: [], // <----- create a new state
    fetchError: null,
}
...
case FILTER_MESSAGE_BY_ORDER:
            return {
                ...state,
                filterState: action.payload,
                filteredMessageList: state.messageList.filter((item)=> { // <----update filteredMessageList (not messageList)
                    return  item.productId === null;
                })
            };

Upvotes: 1

agentp
agentp

Reputation: 425

In your code, each time you dispatch an action, you changed messageList which means the next time you filter, it filter the "changed messageList" --> wrong result

My solution would be create another variable in the store, filteredList for example, each time you dispatch action filter, filteredList will change and show the result on UI.

Upvotes: 0

Marcio Montenegro
Marcio Montenegro

Reputation: 51

Create a variable called lists, with the complete list and another one with the filtered result.

When filtering you will start the filter from the complete list, that will remains intact.

Upvotes: 0

Related Questions