首页 > 解决方案 > React JS 组件未在移动设备中完全呈现

问题描述

我有一个通过 heroku 部署的反应 JS 应用程序。在桌面浏览器上,我可以看到所有渲染的 reactJS 组件。但在移动设备上,我只能看到在设备尺寸内渲染的组件。

这是组件最初加载到移动设备上的时间。向下滚动时应该有更多卡片

没有更多的卡片可见,因为它们在最初加载时超出了视图高度。但是它们在那里-我可以向下滚动到底部,但看不到卡片

但是,如果我关闭/打开设备,或者打开其他应用程序并返回 safari,我可以神奇地看到设备高度内的卡片。

同样,卡片下方没有显示任何内容。如果我重复上面的步骤,我可以看到下面的卡片

这是 git repo 的链接。卡片的 Div 在“src/components/messages.js”中呈现

https://github.com/jessicakwak/hitmeup-client

import React, { Component } from "react";
import "./styles/Messages.css";
import "./styles/NewMessage.css";
import axios from "axios";
import Moment from "react-moment";

class Messages extends Component {
  // Data
  state = {
    messages: [],
    selected: this.props.selected,
    wallOpen: false
  };
  componentDidMount() {
    this.setState(
      {
        selected: this.props.selected,
        wallOpen: this.props.wallOpen
      }, //async function, so do stuffs after this happened
      () => {
        let config = {
          headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }
        };
        axios
          .get(
            `${process.env.REACT_APP_API}/messages?channel=${this.state.selected}`,
            config
          )
          .then(res => {
            res.data.reverse();
            this.setState({ messages: res.data });
          })
          .catch(err => console.log(err));
        this.forceUpdate();
      }
    );
  }

  
  componentWillReceiveProps(newProps) {
    //when the props inherited from Chat changed from [] to something
    this.setState(
      {
        selected: newProps.selected,
        wallOpen: newProps.wallOpen
      }, //async function, so do stuffs after this happened
      () => {
        let config = {
          headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }
        };
        axios
          .get(
            `${process.env.REACT_APP_API}/messages?channel=${this.state.selected}`,
            config
          )
          .then(res => {
            res.data.reverse();
            this.setState({ messages: res.data });
          })
          .catch(err => console.log(err));
        this.forceUpdate();
      }
    );
  }

  // Render
  render() {
    return (
      <div id="messages">
        <div id="content">
          {this.state.messages.map(message => {
            return (
              <div className="message" key={message._id}>
                <div
                  className="userImageMessage"
                  style={{
                    backgroundImage: `url(${message.user.image})`
                  }}
                ></div>
                <div className="usrInfo">
                  <span className="user">{message.user.name}</span>
                  <span className="summaryText first">
                    {" "}
                    wants to meet up at{" "}
                  </span>
                  <span className="location">{message.location}</span>
                  <span className="summaryText"> on </span>
                  <span className="eventDate">
                    <Moment date={message.date} format="ll" />{" "}
                  </span>
                  <span> at </span>
                  <span className="eventTime">
                    <Moment date={message.date} format="LT" />
                  </span>
                </div>
                <div className="body">{message.text}</div>
                <span className="date">
                  <Moment
                    date={message.createDate}
                    format="MMMM Do YYYY, h:mm:ss a"
                  />
                </span>
              </div>
            );
          })}
        </div>
      </div>
    );
  }
}

export default Messages;

提前致谢!

标签: javascriptreactjs

解决方案


目前还不清楚问题到底是什么,但这些更新应该让您的组件代码处于更好的状态。

问题:

  • 将 props 保存到 state 是一种反模式,只需从 props 中消费
  • setState不打算“链接”多个同步状态更新,而是使用生命周期函数
  • 提供足够的初始状态,只取数据componentDidMount
  • 数据获取实际上只依赖于props.selected,因此无需先将其存储在状态中
  • componentWillReceiveProps几乎不推荐使用,使用componentDidUpdate
  • forceUpdate应该真的几乎不需要

解决方案:

  • 将数据提取分解为函数(相对于setState回调):DRY 原则
  • 消费props.selected数据获取:单一事实来源
  • 获取数据componentDidMount:使用生命周期函数
  • 利用componentDidUpdate比较先前和当前props.selected值并重新获取数据:使用生命周期函数

注意:我看不到如何wallOpen使用,所以保留该行为

// Data
state = {
  messages: [],
  wallOpen: this.props.wallOpen, // just set initial wallopen from props
};

fetchMessages = () => {
  const config = {
    headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }
  };
  axios
    .get(
      `${process.env.REACT_APP_API}/messages?channel=${this.props.selected}`,
      config
    )
    .then(res => {
      res.data.reverse();
      this.setState({ messages: res.data });
    })
    .catch(err => console.log(err));
}

componentDidMount() {
  this.fetchMessages();
}

componentDidUpdate(prevProps) {
  const { selected, wallOpen } = this.props;

  // if selected prop changed, refetch data
  if (prevProps.selected !== selected) {
    this.fetchMessages();
  }

  // if new wallOpen prop changed, store it
  if (prevProps.wallOpen !== wallOpen) {
    this.setState({ wallOpen });
  }
}

推荐阅读