I don´t know why my users are undefined in my console.log I can see them in my State but I can´t list them on the page .. It showed up before where I have not yet used Redux .. after using Redux it no longer works that the users are displayed.
I'll show you a piece of the code where it should be displayed and how My UserManagement.js:
function UserManagement({ history }) {
const dispatch = useDispatch();
const userLogin = useSelector((state) => state.userLogin);
const userList = useSelector((state) => state.userList);
const { loading } = userLogin;
const { users} = userList;
useEffect(() => {
dispatch(getUsers());
},[dispatch, history]);
const deleteHandler = (id) => {
if (window.confirm("Are you sure? you want to delete")) {
dispatch(deleteUserAction(id));
}
};
console.log(userList);
console.log(users);
return (
<MainScreen title={`List of Users`}>
<Link to="/createUser" id="OpenCreateUserDialogButton">
<Button style={{ marginLeft: 10, marginBottom: 6 }} size="lg">
Create new User
</Button>
</Link>
{loading && <Loading />}
{users &&
users?.map((users) => (
<Accordion>
<Card style={{ margin: 10 }} key={users._id}>
<Card.Header style={{ display: "flex" }}>
<span
// onClick={() => ModelShow(note)}
style={{
color: "black",
textDecoration: "none",
flex: 1,
cursor: "pointer",
alignSelf: "center",
fontSize: 18,
}}
>
{users.userID}
</span>
<div>
<Link to="/profileedit">
<Button
id="EditButton"
>Edit</Button>
</Link>
<Button
id="DeleteButton"
variant="danger"
className="mx-2"
onClick={() => deleteHandler(users.id)}
>
Delete
</Button>
</div>
</Card.Header>
I will show my Reducer function:
export const userListReducer = (state = {}, action) => {
switch (action.type) {
case USER_LIST_REQUEST:
return { loading: true };
case USER_LIST_SUCCESS:
return { loading: true, userList: action.payload, success: true };
case USER_LIST_FAIL:
return { loading: false, error: action.payload, success: false };
default:
return state;
}
}
And this is my userAction:
export const getUsers = (user) => async (dispatch, getState) => {
try {
dispatch({ type: USER_LIST_REQUEST });
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
Authorization: `Bearer ${userInfo.token.token}`,
},
};
const url = "http://localhost:8080/user/"
const { data } = await axios.get(url, config);
dispatch({ type: USER_LIST_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: USER_LIST_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
CodePudding user response:
Following my comment on your question.
This is how you should be using a state variable.
function UserManagement({ history }) {
const dispatch = useDispatch();
const userList = useSelector((state) => state.userList);
useEffect(() => {
dispatch(getUsers());
},[dispatch, history]);
useEffect(() => {
console.log(userList);
},[userList]);
...
}
If you still need to create another variable, you need to assign it a value every time userList changes - by adding this line to the useEffect method just like this.
function UserManagement({ history }) {
const dispatch = useDispatch();
const userList = useSelector((state) => state.userList);
let users = userList;
useEffect(() => {
dispatch(getUsers());
},[dispatch, history]);
useEffect(() => {
users = userList;
},[userList]);
...
}
Notice that when you assign a value to a variable like this:
The value assigned to that variable is the initial value of the assigned variable (undefined) because the reducer has not yet updated the state value. And when it actually updates it, nothing updates the second variable you created "users"
const userList = useSelector((state) => state.userList);
const users = userList;
And you can use it to manipulate your UI by:
{userList &&
userList.map((users) => (
<MyComponent/>
)
}
CodePudding user response:
I added a comment to this question,so check that too.
However I just noticed something else that should help you.
Due the the way state works your users are probably returning as undefined
You have two choices here.
Change your
users.map()touserList.users.map()as userList.If you really want it to just be
users.map()then you might have to use some react state. For example
import { useSelector } from 'react-redux';
import { useEffect, useState } from 'react';
import { MyUserComponent } from 'some_file';
const YourComponent = () => {
// grab your userList from redux
const userList = useSelector(state => state.userList);
// create some state for use the users
// an empty array to start
const [users, setUsers] = useState([]);
// watch the userList for changes
useEffect(() => {
// update the users state whenever
// there is a change to useList
setUsers(userlist.users)
}, [userList])
// do whatever you want in your return
return (
<div>
{
users.map(user => <MyUserComponent {...user} key={`user-${index}`}) />
}
</div>
)
}
Honestly I'd just do option 1
