怎么可能在 API 调用和 setState 之后,同一个对象的某些元素可以访问,而其他元素不能访问?

Posted

技术标签:

【中文标题】怎么可能在 API 调用和 setState 之后,同一个对象的某些元素可以访问,而其他元素不能访问?【英文标题】:How is it possible that after API call and setState, some elements of the same object are accessible, while others aren't? 【发布时间】:2020-04-13 20:59:25 【问题描述】:

这里有一些代码

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: Cannot read property 'map' of undefined

它们包含在同一个状态对象中,所以我不明白这怎么可能。我确定数组在那里!

【问题讨论】:

能否展示整个组件,包括初始状态分配? 【参考方案1】:
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
  

您可能还想在此处展平您的状态,您可以阅读更多关于in this question的内容

【讨论】:

是的,我就是这样修复它的 【参考方案2】:

尽管 1.componentWillMount 2.render 的顺序是正确的,但您的 this.state.currentImage 的异步初始化似乎是问题没有?

它将在 axios 调用完成之前渲染并实际将数据设置为状态。

一个简单的解决方法是添加 undef 检查:

this.state.currentImage.tags && this.state.currentImage.tags.map(tag => <p>tag</p>)

【讨论】:

否,因为 this.state.currentImage 中的其他项目(如“description”和“author”)渲染得很好,而且图像但不是数组。它们位于同一个 currentImage 中,它们来自 axios 调用。尝试了你的修复,同样的错误。 我应该将检查添加到 currentImage.tags 一件事!但是,是的,这可能是标签实际进入方式的问题。您能否调试对象以查看标签数组的外观? 我已经在问题之前进行了调试。这就是为什么我确定数组在那里。这是 console.log(res.data.picsData[this.props.match.params.imageId].tags) i.ibb.co/G94n1RS/Screenshot-at-2019-12-22-02-02-43.png 的输出 不知道为什么。您是否尝试过 this.state.currentImage.tags &&,也许没有看到额外的渲染,并且此检查将允许使用实际数据重新渲染.. 想通了。问题是它渲染了多次,但第一次渲染的状态尚未设置,但由于 array.map 是一个给出错误的函数。【参考方案3】:

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

【讨论】:

以上是关于怎么可能在 API 调用和 setState 之后,同一个对象的某些元素可以访问,而其他元素不能访问?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 setState 之后调用 getDerivedStateFromProps?

在等待之后调用 setState 时,状态立即可用

在 dispose() 之后调用 setState()

更新状态 - 为啥在调用 setState 时创建新的状态副本?

react的setState使用中遇到的问题

如何在useEffect(func,[])中使用异步api调用中的setState钩子测试组件