我正在使用react redux。在此Profiles组件中,我使用componentWillMount中的this.startSetUsers来触发从mongodb中提取用户并将其存储到状态。然后我mapStateToProps从状态获取用户作为道具,所以我得到this.props.users。 然后在渲染中我尝试将用户作为道具传递给ProfilesList组件并渲染它,或者如果没有用户从Profile组件中渲染没有用户。
现在这可以工作,如果状态为空并且我导航到ProfilesList或者如果我使用ProfilesList组件刷新该特定URL但是如果通过startSetUser转到ProfilePage组件我只获得一个处于状态的用户并在ProfilePage中显示它然后从那里组件现在状态有一个用户我试图通过<来到ProfilesList链路>显示所有用户< /链接>我得到一个错误“this.props.users.map不是一个函数”,我猜这是因为mapStateToProps在渲染和使用this.props.users.map之前没有完成
我希望有人理解我,这有点拗口。 :D有一些工作吗?
class Profiles extends React.Component {
componentWillMount() {
this.props.startSetUsers()
}
render() {
return(
<div className="content-container content-container--list">
<div className="list-header">
<div className="show-for-mobile">Users</div>
<div className="show-for-desktop">User</div>
<div className="show-for-desktop">Joined</div>
</div>
<div className="list-body">
{this.props.users.length === 0 ? (
<div className="list-item list-item--message">
<span>No users</span>
</div>
) : (
this.props.users.map((user) => {
return <ProfilesList key={user._id} {...user} />
})
)
}
</div>
</div>
)
}
}
const mapStateToProps = (state) => ({
users: state.user
})
export default connect(mapStateToProps, actions)(Profiles)
ProfilesList
const ProfilesList = ({ username, email, created_at, avatar }) => (
<Link className="list-item" to={`/user/${username}`}>
<div className="list-item__avatar-title">
<div className="list-item__avatar">
<img src={avatar || 'https://image.ibb.co/bUv8k7/NoImage.png'} />
</div>
<div>
<h3 className="list-item__title">{username}</h3>
<span className="list-item__sub-title">{email}</span>
<br />
<span className="list-item__sub-title">List of articles: X</span>
</div>
</div>
<div>
<h4 className="list-item__joined">{moment(created_at).format('MMMM Do, YYYY')}</h4>
</div>
</Link>
)
export default ProfilesList;
资料
class Profile extends React.Component {
constructor(props) {
super(props);
this.state = {
usersLoaded: false
};
}
componentWillMount() {
this.props.startSetUser(this.props.match.params.id)
}
render() {
return(
<div>
{
this.props.user && this.props.match.params.id ?
<ProfilePage {...this.props}/> :
<div>404</div>
}
</div>
)
}
}
const mapStateToProps = (state, props) => ({
user: state.user
})
export default connect(mapStateToProps, actions)(Profile)
ProfilePage
const ProfilePage = props => {
const {user} = props;
return (
<div className="section">
<div className="profile__header">
<div className="profile__name">
<h2>{`${user.firstName} ${user.lastName}`}</h2>
<h3>{user.email}</h3>
</div>
</div>
<div className="profile__content">
<div className="photo-container">
<div className="photo">
<img src={user.avatar || 'https://image.ibb.co/bUv8k7/NoImage.png'} />
</div>
</div>
<div className="profile__info">
<p>Username: <strong>{user.username}</strong></p>
<li>Email: <strong>{user.email}</strong></li>
<li>Location: <strong>{user.location}</strong></li>
<li>City: <strong>{user.city || renderMessage}</strong></li>
<li>Birthday: <strong>{`${user.day} ${user.month}, ${user.year}`}</strong></li>
<li>Gender: <strong>{user.gender}</strong></li>
<li>Joined: <strong>{moment(user.created_at).format('MMMM Do, YYYY')}</strong></li>
</div>
<div className="profile__button">
<button className="button">Edit</button>
<Link to="/users" className="button">List of all users</Link>
</div>
</div>
</div>
);
};
export default ProfilePage;
减速器
const userReducer = (state = [], action) => {
switch (action.type) {
case 'SET_USER':
return action.user;
case 'SET_USERS':
return action.users;
default:
return state;
}
};
export default userReducer;
编辑:忘记发布动作
// SET_USER
export const setUser = (user) => ({
type: 'SET_USER',
user
})
export const startSetUser = (username) => {
return (dispatch) => {
axios.get(`${ROOT_URL}/user/${username}`)
.then(response => {
dispatch(setUser(response.data))
})
}
}
// SET_USERS ALL
export const setUsers = (users) => ({
type: 'SET_USERS',
users
})
export const startSetUsers = () => {
return (dispatch) => {
axios.get(`${ROOT_URL}/users`)
.then(response => {
dispatch(setUsers(response.data))
})
}
}
答案 0 :(得分:0)
看起来你的减速机存在问题:
const userReducer = (state = [], action) => {
switch (action.type) {
case 'SET_USER':
return action.user;
case 'SET_USERS':
return action.users;
default:
return state;
}
};
export default userReducer;
您正在使用state
和action.user
覆盖action.users
。我猜测action.user
是一个对象而action.users
是一个数组。因此,当ProfileList
呈现时,它会看到this.state.users
存在,但是您将其设置为对象而不是数组。
我会在userReducer
中为activeUser
创建一个新属性,或者创建一个新的reducer来处理保存活动用户。
const initialState = {
activeUser: null,
users: []
};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'SET_USER':
state.activeUser = action.user;
return state;
case 'SET_USERS':
state.users = action.users
return state;
default:
return state;
}
};
export default userReducer;
答案 1 :(得分:0)
谢谢Chase,你让我思考正确的方向,我设法找到解决方案,减速器确实是问题
我已将减速器更改为此
const userReducer = (state = {}, action) => {
switch (action.type) {
case 'SET_USER':
return { ...state, user: action.payload }
case 'SET_USERS':
return { ...state, users: action.payload }
default:
return state;
}
};
export default userReducer;
它有效:)
此处是我更改为使用新更改的减速器
的操作// SET_USER
export const setUser = (user) => ({
type: 'SET_USER',
payload: user
})
export const startSetUser = (username) => {
return (dispatch) => {
axios.get(`${ROOT_URL}/user/${username}`)
.then(response => {
dispatch(setUser(response.data))
})
}
}
// SET_USERS ALL
export const setUsers = (users) => ({
type: 'SET_USERS',
payload: users
})
export const startSetUsers = () => {
return (dispatch) => {
axios.get(`${ROOT_URL}/users`)
.then(response => {
dispatch(setUsers(response.data))
})
}
}