【问题标题】:When I map over a populated array in this.state, why does it return undefined?当我映射 this.state 中的填充数组时,为什么它返回未定义?
【发布时间】:2019-01-06 06:37:39
【问题描述】:

在我的应用程序中,我有一个在用户登录后呈现的 home 组件。在这个主组件的 componentDidMount 中,我获取与登录用户关联的文档。 fetch 调用有效,响应中填充了正确的数据。我获取这些数据并调用 this.setState,将获取的数据设置为 this.state。

在主组件渲染函数中,我插入了 JSX,它调用一个函数来映射 this.state.docs 并显示该数据。尽管 this.state 中的数据可以成功记录到 Home 组件的渲染函数中,但映射到数据的结果总是返回 undefined。

如果我创建一个新文档,它会被插入并正确显示,但旧文档永远不会显示。

这是我的主组件:

import React from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';

const axiosConfig = {
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
};

class Home extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      docs: [],
      username: '',
      userid: '',
      newDocumentName: '',
      newDocumentPassword: '',
      loading: true
    };
    console.log('this.props in home constructor ', this.props);
  }

  newDoc() {
    console.log('this.state before new doc ', this.state);
    axios(localStorage.getItem('url') + '/newDoc', {
      method: 'post',
      data: {
        title: this.state.newDocumentName,
        password: this.state.newDocumentPassword
      },
      withCredentials: true
    }).then(resp => {
      console.log('the response to new doc ', resp);
      this.setState({
        docs: [...this.state.docs, resp.data.document],
        newDocumentName: '',
        newDocumentPassword: ''
      });
    });
  }

  renderDocumentList() {
    return this.state.docs.map((doc, i) => (
      <div key={i}>
        <Link to={`/editDocument/${doc._id}`}>{doc.title}</Link>
      </div>
    ));
  }

  logout() {
    axios
      .post('http://localhost:3000/logout')
      .then(resp => {
        this.props.history.replace('/');
      })
      .catch(error => console.log(error));
  }

  async componentDidMount() {
    try {
      let resp = await axios
        .get(
          localStorage.getItem('url') +
            '/getAllDocs/' +
            this.props.match.params.userid,
          axiosConfig
        )
        .then(resp => {
          console.log('awaited response in comp did mount of home ', resp);
          this.setState({
            docs: [resp.data.docs],
            username: resp.data.username,
            userid: resp.data.userid,
            loading: false
          });
        });
    } catch (e) {
      console.log(e);
    }
  }

  render() {
    if (this.state.loading) {
      return (
        <div>
          <h2>Loading...</h2>
        </div>
      );
    } else {
      return (
        <div className="page-container">
          <div className="document-header">
            <button className="logout-button" onClick={() => this.logout()}>
              Logout
            </button>
            <h3>Welcome, {this.state.username}.</h3>
          </div>
          <div className="create-or-share-document-div">
            <input
              type="text"
              placeholder="New document name"
              name="newDocumentName"
              value={this.state.newDocumentName || ''}
              onChange={event => {
                this.setState({ newDocumentName: event.target.value });
              }}
              style={{ width: '30%' }}
            />
            <input
              type="password"
              placeholder="new document password"
              name="newDocumentPassword"
              value={this.state.newDocumentPassword || ''}
              onChange={event => {
                this.setState({ newDocumentPassword: event.target.value });
              }}
              style={{ width: '30%' }}
            />
            <button
              style={{
                border: 'solid black 1px',
                padding: '5px',
                borderRadius: '10px',
                height: '3%',
                backgroundColor: 'lightgrey'
              }}
              onClick={() => this.newDoc()}
            >
              Create Document
            </button>
          </div>
          <div className="document-container">
            <div className="document-list">
              <p>My Documents:</p>
              <ul>{this.renderDocumentList()}</ul>
            </div>
          </div>
          <br />
          <div className="create-or-share-document-div">
            <input
              style={{ width: '30%' }}
              type="text"
              placeholder="paste a docID to collab on a doc"
              ref="sharedDoc"
            />
            <button
              style={{
                border: 'solid black 1px',
                padding: '5px',
                borderRadius: '10px',
                height: '3%',
                backgroundColor: 'lightgrey'
              }}
            >
              Add Shared Doc
            </button>
          </div>
        </div>
      );
    }
  }
}

export default Home;

【问题讨论】:

  • 您确定应该是docs: [resp.data.docs] 而不是docs: resp.data.docs?可能是您在数组中创建了一个数组。
  • 谢谢,托勒。这解决了问题。我不知道为什么,但你的答案旁边没有复选标记表示正确,但 100% 这解决了我的问题。
  • 太棒了!我在下面添加了一个答案。

标签: javascript reactjs array.prototype.map


【解决方案1】:

您正在将状态中的docs 设置为[resp.data.docs],这是数组中的一个数组。直接使用resp.data.docs 数组:

this.setState({
  docs: resp.data.docs,
  username: resp.data.username,
  userid: resp.data.userid,
  loading: false
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    相关资源
    最近更新 更多