javascript - Keeping data object after filtering -
small background intro
i´m working user administration page of project , running small problem here. have table contains material-ui`s usercard. each user uses system exist´s 1 card. card´s generated data comes database , written redux store.
the admin can several interactions database changes userdata. provide easy way find specific user <textfield />
implemented filter´s table of usercards.
all of things mentioned here works!
the problem
as mentioned in intro data stored in redux store. when filter data, action dispatched
export const filter_all_user_by_name = "filter_all_user_by_name" export const filter_all_user_by_department = "filter_all_user_by_department" export default function filteralluser(filter, filteroption){ return (dispatch, getstate) => { if(filteroption === 'name'){ return dispatch (filteruserbyname(filter)) }else{ return dispatch (filteuserbydepartment(filter)) } } } function filteruserbyname(filter){ return { type: filter_all_user_by_name, filter: filter } } function filteuserbydepartment(filter){ return { type: filter_all_user_by_department, filter: filter } }
the reducer
even if reducers works, main reason problem.
why?
it because, when filter data not able really filter state, rather return new state object leads me problem alluserdata
, filtereduserdata
out of sync after userdata changed.
let me explain in code
function alluser(state = {alluserdata: []}, action){ switch (action.type){ case 'request_all_user': return object.assign({}, state, { isfetching: true }); case 'receive_all_user': return object.assign({}, state, { isfetching: false, alluserdata: action.items }); case 'filter_all_user_by_name': return object.assign({}, state, { filtereduserdata: state.alluserdata.filter(user => user.usernamelast.tolowercase().indexof(action.filter.tolowercase()) >= 0) }); case 'filter_all_user_by_department': return object.assign({}, state, { filtereduserdata: state.alluserdata.filter(user => user.departmentname.tolowercase().indexof(action.filter.tolowercase()) >= 0) }); default: return state } }
but when i´m trying filter original state , user removes filter, data didn´t matched filter gone.
case 'filter_all_users': return allusers.filter(user => user.usernamelast.tolowercase().indexof(action.filter.tolowercase()) >= 0);
how can filter state, keep data ?
as requested, have put code you. below.
as side note, pass filter { field: 'userlastname', text: your filter text
} filter criteria. or make more scalable, can pass filter-handler instead of text above. way can have type of filter, , not text filters.
export default function alluser(state = {alluserdata: [], filters: {}, filtereduserdata: []}, action){ switch (action.type){ case 'request_all_user': return { ...state, isfetching: true }; case 'receive_all_user': return { ...state, isfetching: false, alluserdata: action.items, filtereduserdata: filterdata(action.items, state.filters), }; case 'filter_all_user_by_name': { const updatedfilters = { ...state.filters, usernamelast: action.filter } return { ...state, filtereduserdata: filterdata(state.alluserdata, updatedfilters), filters: updatedfilters }; } case 'filter_all_user_by_department': { const updatedfilters = { ...state.filters, departmentname: action.filter } return { ...state, filtereduserdata: filterdata(state.alluserdata, updatedfilters), filters: updatedfilters }; } default: return state } } const filterdata = (users, filters) => { return users.filter(filterfn(filters)); }; const filterfn = filters => item => object.keys(filters).reduce((res, filter) => { return res && item[filter].tolowercase().indexof(filters[filter].tolowercase()) >= 0; }, true);
unit tests
import usersreducer './users'; describe('usersreducer', () => { describe('receive_all_user', () => { const receive_all_user = 'receive_all_user'; it('should replace users in state', () => { const initialstate = { isfetching: false, alluserdata: [{ name: 'a' }], filters: {}}; const newusers = [{ name: 'b' }]; const newstate = { ...initialstate, alluserdata: newusers, filtereduserdata: newusers}; expect(usersreducer(initialstate, { type: receive_all_user, items: newusers })).toequal(newstate); }) }) describe('filter_all_user_by_name', () => { let filter_all_user_by_name = 'filter_all_user_by_name'; it('should filter users name', () => { const initialstate = { isfetching: false, alluserdata: [{ usernamelast: 'doe' }, { usernamelast: 'smith' }], filters: {}}; const filtertext = 'd'; const finalstate = { isfetching: false, alluserdata: [{ usernamelast: 'doe' }, { usernamelast: 'smith' }], filters: { usernamelast: filtertext }, filtereduserdata: [{ usernamelast: 'doe' }] }; expect(usersreducer(initialstate, { type: filter_all_user_by_name, filter: filtertext})).toequal(finalstate); }) }) describe('filter_all_user_by_department', () => { let filter_all_user_by_department = 'filter_all_user_by_department'; it('should filter users department', () => { const initialstate = { isfetching: false, alluserdata: [{ departmentname: 'it' }, { departmentname: 'human resources' }], filters: {}}; const filtertext = 'it'; const finalstate = { ...initialstate, filters: { departmentname: filtertext }, filtereduserdata: [{ departmentname: 'it' }] }; expect(usersreducer(initialstate, { type: filter_all_user_by_department, filter: filtertext})).toequal(finalstate); }) }) });
Comments
Post a Comment