React JS组件未在移动设备中完全呈现

时间:2020-04-09 03:11:31

标签: javascript reactjs

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

This is when the components were initially loaded on mobile. There should be more cards when scrolled down

No more cards are visible because they were outside of view height when initially loaded. But they are there- I can scroll down to the bottom but just can't see the cards

however, if I turn off/on the device, or turn on other apps and come back to safari, I can magically see the cards within the device height.

again, there is nothing showned below the cards. If I iterate steps above, I can see the cards below

这是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;

提前谢谢!

1 个答案:

答案 0 :(得分:0)

目前尚不清楚问题的实质,但是这些更新应该使您的组件代码更美观。

问题:

  • 让道具进入状态是一种反模式,只是从道具中消费
  • 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 });
  }
}