Как это возможно, что после вызова API и setState некоторые элементы одного и того же объекта доступны, а другие нет? - PullRequest
0 голосов
/ 22 декабря 2019

Итак, вот некоторый код

componentWillMount = () => {
    var URL = 'http://localhost:8000/requests'
    axios({
        url: URL,
        method: 'post', 
        data: {
            message: 'getImages'
        }
    }).then(res => {
        this.setState({currentImage: res.data.picsData[this.props.match.params.imageId]})
    })
}
render() {
    return (
        <div className="image-component-wrapper">
            <img src={'../content/' + this.state.currentImage.fileName} /> 
            <div className="image-meta">
                <p className='image-metadescription'{this.state.currentImage.description</p>
                <p className='image-meta-author'>Uploaded by:
                <i className='image-meta-author-name'>{this.state.currentImage.author}</i></p>
                <div className='image-meta-tags'>
                    Tags:
                    {this.state.currentImage.tags.map(tag => <p>{tag}</p>)}
                </div>
            </div>
        </div>
    )
}

Изображение отображается так, как должно. Два тега P и тег I также, но я не могу получить массив тегов для отображения вообще. Это дает мне Uncaught TypeError: Невозможно прочитать свойство 'map' из undefined

Они содержатся в одном и том же объекте состояния, поэтому я не понимаю, как это возможно. Массив есть, я уверен!

Ответы [ 3 ]

1 голос
/ 22 декабря 2019

Несмотря на то, что последовательность 1. componentWillMount 2. рендеринга правильная, ваша асинхронная инициализация this.state.currentImage, похоже, является проблемой нет?

Он будет рендериться до завершения вызова axios и фактически установитданные к состоянию.

Простое решение - добавить проверку undef:

{this.state.currentImage.tags && this.state.currentImage.tags.map(tag => <p>{tag}</p>)}
1 голос
/ 22 декабря 2019
this.state.currentImage.tags.map(tag => <p>{tag}</p>)

Вы пытаетесь получить доступ к this.state.currentImage.tags.map здесь, но ваше начальное состояние определяется как

this.state = { currentImage: {} }

Это означает, что this.state.currentImage.tags не определено, что вы также можете увидеть в сообщении об ошибке, которое вывы получаете, когда вы пытаетесь вызвать tags.map

Uncaught TypeError: Cannot read property 'map' of undefined

Чтобы исправить это, вам нужно убедиться, что вы определяете все, что вы используете в своем состоянии в своем конструкторе, например

this.state = {
  currentImage: {
    author: "",
    description: "",
    tags: []
    // etc
  }
}

Вы также можете сгладить свое состояние здесь, о чем вы можете прочитать больше о в этом вопросе

0 голосов
/ 22 декабря 2019

@ Xetera

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { addPics, setCurrentPic } from '../../redux/actions';
import axios from 'axios';
import { Link } from 'react-router-dom';


class ImageComp extends Component {
    constructor(props) {
        super(props)
        this.state = { currentImage: {}, imageId: this.props.match.params.imageId }
    }
    componentWillMount = () => {
        var URL = 'http://localhost:8000/requests'
        axios({
            url: URL,
            method: 'post',
            data: {
                message: 'getImages'
            }
        }).then(res => {
            this.setState({ currentImage: res.data.picsData[this.props.match.params.imageId] })
        })
    }

    render() {
        return (
            <div className="image-component-wrapper">
                <img src={'../content/' + this.state.currentImage.fileName} />
                <div className="image-meta">
                    <p className='image-meta-description'>{this.state.currentImage.description}</p>
                    <p className='image-meta-author'>Uploaded by:
        <i className='image-meta-author-name'>{this.state.currentImage.author}</i></p>
                    <div className='image-meta-tags'>
                        Tags:
                        {this.state.currentImage.tags.map(tag => <p>{tag}</p>)}
                    </div>
                </div>
            </div>
        )
    }
}
const mapStateToProps = (state) => {
    console.log(state)
    return { pics: state.pics, pic: state.pic }
}


export default connect(mapStateToProps, { addPics, setCurrentPic })(ImageComp)
...