Reputation: 2572
Versions
Material-UI: 0.18.0
React: 15.5.4
Redux: 3.6.0
Browser: Chrome -- Version 59.0.3071.115 (Official Build) (64-bit)
Problem
I am using redux for application wide state management instead of setState. When calling redux actions the checkbox doesn't register as checked, but it registers that it was clicked when I console.log the onRowSelection
. If I remove the line calling my action, the checkboxes work just fine. For some reason, Material UI is blocked from updating when I call my redux action.
--Edit--
It appears that it's not the action that is causing the malfunction it's something about my reducer that material UI's Table doesn't like.
(added reducer snippet below)
Table Component
class AdminDeptAppAccess extends React.Component {
_onRowSelection (selectedUsers, props) {
console.log(selectedUsers)
props.selectedUsersAction(filterUsers(selectedUsers, props.deptAppRoles))
}
render () {
return (
<Table
selectable
multiSelectable
onRowSelection={(selectedUsers) => this._onRowSelection(selectedUsers, this.props)}
>
{/* contents */}
</Table>
)
}
}
const filterUsers = (selectedUsers, deptAppRoles) => {
if (selectedUsers === 'all') {
return deptAppRoles
} else if (selectedUsers === 'none') {
return []
} else if (selectedUsers === []) {
return []
} else {
let users = []
selectedUsers.map((num, i) => (
users.push(deptAppRoles[num])
))
return users
}
}
applicable redux action that was passed down via props
export const selectedUsersAction = (users) => {
console.log('selectedUsersAction', users)
return dispatch => {
dispatch({
type: 'SELECTED_USERS',
selectedUsers: users
})
}
}
applicable reducer
const admin = (state = { selectedUsers: [] }, action) => {
switch (action.type) {
// ...
case 'SELECTED_USERS':
return Object.assign({}, state, {
selectedUsers: action.selectedUsers
})
default:
return state
}
}
screenshot
ignore the console errors, they are from something else.
I selected the first row, and the console registers that [0] was clicked, and my redux action registers who got clicked, but the checkbox doesn't update because my redux action (reducer) somehow blocked the component from rendering the updated checkbox.
Upvotes: 2
Views: 1935
Reputation: 381
The problem here is that your reducer is working with an immutable state (by using Object.assign
). This is a good way to write a reducer (or using spread notation), but it's causing a problem here.
When you set the new selectedUsers
in the reducer you are also creating a new copy of state and replacing the old one. I'm guessing you are storing the actual data used to generate the table in same reducer as the selectedUsers
(an array of user objects?). When you use Object.assign({}, state, etc....
you are creating new instances of every property on the state object. This includes the array of user objects used to generate the table rows.
The table component must be registering that this array is new and forcing a re-render or clearing the current selected state based on the fact that the array has been replaced.
I had the same problem and I started off with this fix -
const admin = (state = { selectedUsers: [] }, action) => {
switch (action.type) {
// ...
case 'SELECTED_USERS':
state.selectedUsers = action.selectedUsers
return state
default:
return state
}
}
It worked, but I didn't like it.
So I opted to store my selectedUsers
in a separate reducer to the actual user data used to generate the table and that also fixed my problem. It's not the best fix in the world, but it works and it's better than sacrificing immutability.
So for the time being I have a separate selected
reducer for my different table views. I think I'll need to find a better solution in the long run.
Upvotes: 2