当前位置: 首页 > 知识库问答 >
问题:

反应等待组件从存储中获取状态,然后呈现子级

张鸿宝
2023-03-14

我正在使用react redux。在这个Profiles组件中,我使用这个。Component中的startSetUsers将装载以触发从mongodb获取用户并将其存储到state。然后我映射StateToprops以从state获取用户作为道具,所以我得到了这个。道具。用户。然后在render中,我尝试将用户作为道具传递给ProfilesList组件并进行渲染,或者如果没有用户,则从Profile组件中渲染没有用户。

现在,如果状态为空,我导航到ProfilesList,或者如果我使用ProfilesList组件刷新特定url,但如果转到ProfilePage组件,通过startSetUser,我只获得状态中的一个用户,并在ProfilePage中显示它,然后从该组件中,现在状态有一个用户,我尝试通过该组件转到ProfilesList

我希望有人能理解我的意思,这有点过分了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)

剖面图

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)

档案页

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))
      })
  }
}

共有2个答案

龙俊德
2023-03-14

谢谢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))
      })
  }
}
燕光熙
2023-03-14

看起来这是你减速器的问题:

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;

您正在用操作覆盖状态。用户操作。用户。我将猜测动作。用户是一个对象和动作。用户是一个数组。所以当ProfileList呈现时,它会看到这个。状态用户存在,但您将其设置为对象而不是数组。

我将在userReucer中为activeUser创建一个新属性,或者创建一个新的减速器来处理保存活动用户。

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;
 类似资料:
  • 问题内容: 我正在使用@ font- face将字体嵌入到我的网站中。首先,文本将作为系统默认值呈现,然后(假定字体文件已加载)正确的字体将在几分之一秒后呈现。有没有一种方法可以通过延迟页面渲染直到加载字体或类似字体之后来最小化/消除此延迟。 问题答案: 这取决于浏览器的行为方式。 首先,您的@font在哪里声明?它是内联到HTML,是在页面上的CSS表中声明,还是(希望)在外部CSS表中声明?

  • 在这个例子中,我想在我的父组件中使用我的子组件的状态。

  • 这是一个更大的组件的一部分,但我在下面的一个可重复的例子中总结了它: 我知道React中的组件在状态改变时会重新呈现,为什么将新数组设置为状态不会触发这个呢?但是在清除状态时rerender是明显的? 我的沙盒:https://codesandbox.io/s/immutable-sun-oujqj?file=/src/app.js

  • 问题内容: 在React中,这两种实现之间有什么真正的区别?一些朋友告诉我,FirstComponent是模式,但是我不明白为什么。SecondComponent看起来更简单,因为渲染仅被调用一次。 第一: 第二: 更新:我将setState()更改为this.state = {}(感谢joews),但是,我仍然看不到区别。一个比另一个好吗? 问题答案: 应该注意的是,复制永远不会更改为状态的属性

  • 我用绝地武士连接redis服务器。Redis ip值在一个单独的文件中配置,我试图在初始化期间加载该文件 我从redis获取多个密钥的方法如下 当我在属性文件中给出了不正确的ip值时,访问它的请求线程等待了很长一段时间。我的请求不应该因为池中资源不可用而停止。 在这里,我附加了停顿线程的线程转储(即;处于等待状态的线程) 我怎样才能做到这一点?非常感谢您的帮助。提前感谢:-)