【问题标题】:Jsx does not show props properlyJsx 没有正确显示道具
【发布时间】:2018-06-11 14:49:33
【问题描述】:

我正在通过创建应用程序来学习反应,但我的代码中有一个奇怪的问题,有人可以指出错误吗?谢谢

 test=()=>{
        console.log('filtered card: ',this.state.cards.filter(c=>c.id===this.state.idToDelete)[0].name)

    }

当我使用此函数测试代码行时,它可以正常工作,并且在我单击时正确显示所有名称,但是当我应用该行进行渲染时,我可以将名称放入我的 Jsx 中给我错误?

    const warningCard=this.state.idToDelete && this.state.cards.filter(c=>c.id===this.state.idToDelete)[0].name.toUpperCase()
    return(
        <div>

        <button onClick={this.test}>test</button>
        <button onClick={()=>this.setState({showForm:!this.state.showForm})}>form</button>
        <button onClick={()=>this.setState({showEditForm:false})}>close edit from</button>

        <h2>you have {this.state.cards.length} {card}</h2>

        {this.state.showWarning && 
        <div>
            <h2>ARE YOU SURE YOU WANT TO DELETE THIS {warningCard} CARD?</h2>

这是图片

当我使用 console.log 并注释掉 warningCard 时,所有卡片都正确显示了它们的名称,但是当我在其中添加 warningCard 行时出现此错误

如果有帮助,这是我的完整组件

import React from 'react';
import CardList from './cardList';
import CardForm from './cardForm';

    class FlashCardMainPage extends React.Component{
        constructor(){
            super();
            this.state={
                cards:[
                    {...},
                    {...},
                    {...}],
                nextId:3,
                showForm:false,
                showEditForm:false,
                cardToEdit:{},
                showWarning:false,
                confirm:false,
                idToDelete:''
            }
        }

        onCardClick=(id)=>{
            const {cards}=this.state
            const newCardsState=this.state.cards.map((c)=> c.id===id ? {...c,showInfo:!c.showInfo} : c)
            this.setState({cards:newCardsState})
        }

        deleteCard=(id)=>{
            this.setState({showWarning:true})
            this.setState({idToDelete:id})
        }

        editCard=(id)=>{
            const cardToEdit = this.state.cards.filter(c=>c.id===id)
            this.setState({cardToEdit, showEditForm:true})
        }

        onFormSubmit=(cardFromSubmit)=>{
            const newCard={id:this.state.nextId,...cardFromSubmit}
            this.setState({
                cards:[...this.state.cards,newCard], 
                nextId:this.state.nextId+1,
                cardToEdit:{},
                showForm:false
            })
        }

        onEditCardSubmit=(editedCard)=>{
            this.setState({showEditForm:false})
            const cards=this.state.cards.map((c)=>c.id===this.state.cardToEdit[0].id?c={id:c.id,...editedCard}:c)
            this.setState({cards})
        }

        onCloseForm=()=>{
            this.setState({showForm:false, showEditForm:false})
        }

        test=()=>{
            console.log('filtered card: ',this.state.cards.filter(c=>c.id===this.state.idToDelete)[0].name)

        }

        onConfirm=(pass)=>{
            const check=pass
            if(pass){
                const cards=this.state.cards.filter(c=>c.id!==this.state.idToDelete)
                this.setState({cards, showWarning:false}) 
            }else
                this.setState({showWarning:false})
        }

        render(){
            const card=this.state.cards.length===1?'card':'cards'
            const filteredCards = this.state.idToDelete && this.state.cards.filter(c=>c.id===this.state.idToDelete);  
            const warningCard = filteredCards[0] && filteredCards[0].name.toUpperCase();
            return(
                <div>

                    <button onClick={this.test}>test</button>
                    <button onClick={()=>this.setState({showForm:!this.state.showForm})}>form</button>
                    <button onClick={()=>this.setState({showEditForm:false})}>close edit from</button>

                    <h2>you have {this.state.cards.length} {card}</h2>

                    {this.state.showWarning && 
                    <div>
                        <h2>ARE YOU SURE YOU WANT TO DELETE THIS {warningCard} CARD?</h2>
                        <button onClick={()=>this.onConfirm(true)}>Yes</button>
                        <button onClick={()=>this.onConfirm(false)}>No</button>
                    </div>
                    }

                    {this.state.showForm &&
                        <CardForm
                        cardSave={this.onFormSubmit}
                        closeForm={this.onCloseForm}
                        />
                    }

                    {this.state.showEditForm &&
                        <CardForm
                        editCardSave={this.onEditCardSubmit}
                        cardToEdit={this.state.cardToEdit}
                        closeForm={this.onCloseForm}
                        editStatus={this.state.showEditForm}
                        />
                    }

                    <CardList
                        cards={this.state.cards}
                        cardClick={this.onCardClick}
                        deleteCard={this.deleteCard}
                        editCard={this.editCard}
                    />

                </div>
            )
        }
    }

    export default FlashCardMainPage

【问题讨论】:

  • 这是一个非常不安全的操作this.state.cards.filter(c=&gt;c.id===this.state.idToDelete)[0],因为你怎么知道filter的结果不会为空呢?所以由于某种原因它是空的
  • 如果您可以在此处创建代码的工作示例,那么解决问题会容易得多...codesandbox.io
  • 到目前为止,我的应用运行良好。所有卡片都已正确更新和编辑。我只有一个看似简单的问题,但它让我非常头疼。我认为过滤器不会给我一个空数组,因为道具是从数组本身的卡片传递的。

标签: reactjs filter jsx


【解决方案1】:

我想一些守卫可能会在这里帮助你。如果您尝试将第一行更改为两行怎么办?

const filteredCards = this.state.idToDelete && this.state.cards.filter(c=>c.id===this.state.idToDelete);  
const warningCard = filteredCards[0] && filteredCards[0].name.toUpperCase();

【讨论】:

  • 我可以确认它有效,我可以确认删除没有错误但是有一个小问题,第一张卡从来没有名字显示...你能解释一下为什么你的代码有效吗?现在真的很困惑,我怎么才能显示第一个卡名?
  • 好吧,如果不了解代码的更多信息,我认为不可能回答这个问题,即 idToDelete 来自哪里,卡片的结构是什么等等。如果您可以在某些沙箱中提供 reduce 示例,那可能会有所帮助。
  • 至于添加的代码,它只是检查数组是否确实有一个成员,您要获取的名称。这样可以避免出错,因为如果数组为空,它不会尝试获取名称。
  • 我编辑了我的问题并在底部包含了完整的代码,但我是新手,所以我担心他们很草率,但如果你能看一下,idToDelete 来自 Card 组件,并且props 被传递给不同的函数,我使用该 Id 来设置状态 idToDelete。
  • 感谢您添加的代码。如果您可以创建一个工作示例,使用 stackblitz.com 之类的东西或替代在线解决方案,那将更有帮助。
猜你喜欢
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多