簡體   English   中英

×React - TypeError:無法讀取未定義的屬性(讀取“用戶名”)

[英]×React - TypeError: Cannot read properties of undefined (reading 'userName')

任何人都可以解釋我這是我通過我的服務器獲取一個 json 並且該 json 包含我在博客中使用的信息所以我能夠訪問 blog.blogTitle 但我無法訪問 blog.owner.userName 它沒有對我來說很有意義,因為我在狀態上一次設置整個 json 然后使用它可以請任何人告訴我原因嗎? 以及如何避免

function Blog(props) {
    const isUserAuthenticated = useSelector(state => state.getUser.authenticated)

    const user = useSelector(state => state.getUser.user)

    const [blog, setBlog] = useState([])

    const [dataMounted, setDataMounted] = useState(false)

    const [blogComments, setBlogComments] = useState([])

    const handleCommentSubmission = (e) => {
        const body = {
            blogId: blog.id,
            comment: e.comment,
            userName: user.userName
        }
        console.log(body)

        axios.post('http://localhost:8989/blog/comment', body, APIService.config).then(response => {
            console.log(response.data)
        }).catch(err => {
            console.log("Error while fetching comment: " + err)
            console.log("Error while fetching comment Server response: " + err.response)
        })

        return false;
    }

    const commentSchema = yup.object().shape({
            comment: yup
                .string().required('Comment is required')
                .min(2, 'Minimum 2 characters required')
                .max(300, "Maximum 300 characters allowed"),
        }
    );

    useEffect(() => {

        APIService.getBlogById(props.match.params.id).then(response => {
            setBlog(response.data)
            setBlogComments([])

            console.log('comments:', response.data)
            if (!response.data.comments.includes(null)) {
                response.data.comments.forEach(commentId => {
                    APIService.getCommentById(commentId).then(comment => {
                        blogComments.push(comment.data)
                    })
                })
            }

            console.log("Blog comments  ", blogComments)
        }, [])
        setDataMounted(true)

    }, [])

    return (
        <>
            <div className='blog-container'>

                <Card className="bg-dark text-white blog-banner">
                    <Card.Img
                        className='blog-banner'
                        src="https://image.freepik.com/free-vector/abstract-dotted-banner-background_1035-18160.jpg"
                        alt="Card image"/>
                    <Card.ImgOverlay>
                        <Card.Title className='blog-title'>{blog.blogTitle}</Card.Title>
                    </Card.ImgOverlay>

                </Card>


                <Breadcrumb>
                    <Breadcrumb.Item href="#">Home</Breadcrumb.Item>
                    <Breadcrumb.Item href={"/blog/" + blog.blogCategory}>
                        {blog.blogCategory}
                    </Breadcrumb.Item>
                    <Breadcrumb.Item active>{blog.blogTitle}</Breadcrumb.Item>
                </Breadcrumb>

                {dataMounted ?
                    <div className='blog-data-container'>
                        <p className='blog-data'>{blog.data}</p>
                        <p className='blog-owner'>Created By {blog.owner.userName}</p>
                    </div> : <></>
                }

                {isUserAuthenticated ?
                    <div>
                        <EditButton blog={blog}/>
                        <Button className='btn btn-primary'>
                            Delete Blog
                        </Button>
                    </div> : <></>
                }

                {
                    <div className='comment-form'>

                        {dataMounted && isUserAuthenticated ?
                            <Formik
                                initialValues={{
                                    blogTitle: '',
                                    data: '',
                                    blogCategory: '',
                                    accessStatus: ''
                                }}
                                onSubmit={(e) => handleCommentSubmission(e)}
                                validationSchema={commentSchema}
                            >{({
                                   handleSubmit,
                                   handleChange,
                                   handleBlur,
                                   values,
                                   touched,
                                   isValid,
                                   errors,
                               }) => (

                                <Form>
                                    <Form.Group placeholder='Type your blog here'
                                                controlId="blogForm.CommentTextArea">
                                        <Form.Control
                                            as='textarea'
                                            type="textarea"
                                            placeholder="Type your comment here"
                                            name="comment"
                                            value={values.comment}
                                            onChange={handleChange}
                                            isInvalid={!!errors.comment}
                                        />
                                        <Form.Control.Feedback type="invalid">
                                            {errors.comment}
                                        </Form.Control.Feedback>
                                    </Form.Group>

                                    <Button type='submit'
                                            onClick={(e) => handleSubmit(e)}> Add Comment </Button>
                                </Form>
                            )}
                            </Formik>

                            : <></>
                        }
                    </div>}


                <div className='comment-section-container'>
                    <p>{blogComments}</p>
                    {
                        blogComments.map((comment, index) => {
                            return (
                                <Container>
                                    <Row xs={2} md={4} lg={6}>
                                        <Col>1 of 2</Col>
                                        <Col>2 of 2</Col>
                                    </Row>
                                    <Row xs={1} md={2}>
                                        <Col>1 of 3</Col>
                                        <Col>2 of 3</Col>
                                        <Col>3 of 3</Col>
                                    </Row>
                                    <Row xs="auto">
                                        <Col>1 of 3</Col>
                                        <Col>2 of 3</Col>
                                        <Col>3 of 3</Col>
                                    </Row>
                                </Container>
                            )
                        })
                    }
                </div>
            </div>
        </>
    )
}

示例 Json

{id: '617ec3047c63c4643862ae51', blogTitle: 'some blog', data: 'datata', date: 1635698971568, owner: {…}, …}
blogAccessStatus: "PUBLIC"
blogCategory: "TECHNICAL"
blogTitle: "some blog"
comments: Array(1)
0: "617ec91bfdce2653b01b1d66"
length: 1
[[Prototype]]: Array(0)
data: "datata"
date: 1635698971568
id: "617ec3047c63c4643862ae51"
owner:
blogCount: 0
email: "bhavishya20@gmail.com"
userName: "bhavishya"
[[Prototype]]: Object
sharedWith: []
views: 0
[[Prototype]]: Object

setDataMounted(true)指令應該在setBlog(...)之后調用。

您的博客呈現條件取決於dataMounted狀態。

                {dataMounted ?
                    <div className='blog-data-container'>
                        <p className='blog-data'>{blog.data}</p>
                        <p className='blog-owner'>Created By {blog.owner.userName}</p>
                    </div> : <></>
                }

問題是您在回調之外將dataMounted設置為true 這意味着它會在為您的blog數據運行設置狀態的回調之前執行。 您的問題的可能解決方法是

        APIService.getBlogById(props.match.params.id).then(response => {
            setBlog(response.data)
            setBlogComments([])

            console.log('comments:', response.data)
            if (!response.data.comments.includes(null)) {
                response.data.comments.forEach(commentId => {
                    APIService.getCommentById(commentId).then(comment => {
                        blogComments.push(comment.data)
                    })
                })
            }

            console.log("Blog comments  ", blogComments)
            setDataMounted(true) // setDataMounted should be called inside the callback
        }, [])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM