使用 React useContext() 钩子传递对象 [英] Passing an object using React useContext() hook

查看:84
本文介绍了使用 React useContext() 钩子传递对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含项目列表的视图.当我点击其中一个项目时,我想让面板显示所点击项目的所有详细信息.

这是我写的上下文文件

import React, { useContext, useState } from 'react';const ActivityPreviewContext = React.createContext();const ActivityPreviewUpdateContext = React.createContext();导出函数 useActivityPreview() {返回 useContext(ActivityPreviewContext);}导出函数 useActivityPreviewUpdate() {返回 useContext(ActivityPreviewUpdateContext);}导出函数 ActivityPreviewProvider({ children }) {const [activityPreview, setActivityPreview] = useState();功能活动预览更新(数据){设置活动预览(数据);}返回 (<ActivityPreviewContext.Provider value={activityPreview}><ActivityPreviewUpdateContext.Provider value={activityPreviewUpdate}>{孩子们}</ActivityPreviewUpdateContext.Provider></ActivityPreviewContext.Provider>)}

我正在像这样将其包装在我的路线中.到目前为止,这似乎工作正常

<ActivityPreviewProvider><SideMenu/><HomeView/></ActivityPreviewProvider></路线>

HomeView 是我显示长列表的地方.您会注意到 openPeekPanel() 函数正在调用 activityPreviewUpdate(e.currentTarget.id); 这有效,但尝试传递一个对象会给我一个错误.

这是我尝试过的:activityPreviewUpdate(e.currentTarget.id); WORKS: 传递一个数字或字符串activityPreviewUpdate([1,2,3]); WORKS: 传递一个数组activityPreviewUpdate({a:123, b:456}); BREAKS:传递一个数组

我想传递充满数据的整个对象,以便我可以将其添加到侧面板中.

您可以查看下面的代码.

import React, { useState } from 'react';从'react-router-dom'导入{useHistory};从'./ThumbnailGroup'导入缩略图组;从'./PanelPreview'导入PanelPreview;import { useActivityPreview, useActivityPreviewUpdate } from '../context/ActivityPreviewContext';const fakeData = [{编号:100,类型:视频",标题:我的标题",持续时间:2,问题:4,图片:https://picsum.photos/seed/1/200/150"},{编号:101,类型:视频",标题:我的标题",持续时间:2,问题:4,图片:https://picsum.photos/seed/2/200/150"}]const HomeView = (props) =>{const 历史 = useHistory();const [peekActive, setPeekActive] = useState(false);const [activeItem, setActiveItem] = useState(0);const activityPreview = useActivityPreview();const activityPreviewUpdate = useActivityPreviewUpdate();const closePeekPanel = () =>{let section_ele = document.querySelector(section");section_ele.classList.remove(activePanel");setPeekActive(false);}const openPeekPanel = (e) =>{活动预览更新(e.currentTarget.id);let section_ele = document.querySelector(section");section_ele.classList.add(activePanel");setPeekActive(true);}返回 (
<div id="contentArea"><缩略图组名称=收藏夹"data={fakeData} title=最近收藏";onClick={openPeekPanel}/>

{peekActive &&<PanelPreview onClosePanel={closePeekPanel}/>}</节>);};导出默认的 HomeView;

目前我只在侧面板打印 ID.

import React, { useState } from 'react';import { NavLink, useHistory } from 'react-router-dom';从'./Card'导入卡片;从'./Icon'导入图标;导入 { useActivityPreview, ActivityPreviewProvider } from '../context/ActivityPreviewContext';const PanelPreview = (道具) =>{//钩子const 历史 = useHistory();const activityPreview = useActivityPreview();返回 (<Card id="panelPreview"><div className="panelHeader">{<p>{activityPreview}</p>}

</卡片>);};导出默认面板预览;

解决方案

这是因为 React 不会在 HTML 中呈现 JSON,只会呈现字符串.e.currentTarget.id 呈现该字符串,并且 [1,2,3] 被加入并呈现为 123.

如果您计划接受一个对象,您应该考虑在 p 元素中选择该属性.<p>{activityPreview.a}</p> 将显示123 没有错误.

尽管 JSON.Stringify({a:123, b:456}) 可能是您要查找的内容,但要按原样显示整个对象,而不会中断.

I have a view with a list of items. When I click on one of the items I want to have the panel display all the details of the item that was clicked.

Here is the Context File I wrote

import React, { useContext, useState } from 'react';

const ActivityPreviewContext = React.createContext();
const ActivityPreviewUpdateContext = React.createContext();

export function useActivityPreview() {
    return useContext(ActivityPreviewContext);
}

export function useActivityPreviewUpdate() {
    return useContext(ActivityPreviewUpdateContext);
}

export function ActivityPreviewProvider({ children }) {
    const [activityPreview, setActivityPreview] = useState();

    function activityPreviewUpdate(data) {
        setActivityPreview(data);
    }

    return (
        <ActivityPreviewContext.Provider value={activityPreview}>
            <ActivityPreviewUpdateContext.Provider value={activityPreviewUpdate}>
                    {children}
            </ActivityPreviewUpdateContext.Provider>
        </ActivityPreviewContext.Provider>
    )

}

I am wrapping this in my routes like this. This seems to work fine so far

<Route path="/home">
   <ActivityPreviewProvider>
        <SideMenu />
        <HomeView />
    </ActivityPreviewProvider>
</Route>

HomeView is where I have long lists showing up. You will notice openPeekPanel() function is calling activityPreviewUpdate(e.currentTarget.id); this works, but trying to pass an object gives me an error.

this what I've tried: activityPreviewUpdate(e.currentTarget.id); WORKS: passing a number or string activityPreviewUpdate([1,2,3]); WORKS: passing an array activityPreviewUpdate({a:123, b:456}); BREAKS: passing an array

I would like to pass the entire object full of data so I could add it into the side panel.

You could view the code below.

import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import ThumbnailGroup from './ThumbnailGroup';
import PanelPreview from './PanelPreview';
import { useActivityPreview, useActivityPreviewUpdate } from '../context/ActivityPreviewContext';

const fakeData = [
    {
        id: 100,
        type: "video",
        title: "My Title",
        duration: 2,
        questions: 4,
        image: "https://picsum.photos/seed/1/200/150"
    },
    {
        id: 101,
        type: "video",
        title: "My Title",
        duration: 2,
        questions: 4,
        image: "https://picsum.photos/seed/2/200/150"
    }
]

const HomeView = (props) => {

    const history = useHistory();
    const [peekActive, setPeekActive] = useState(false);
    const [activeItem, setActiveItem] = useState(0);
    
    const activityPreview = useActivityPreview();
    const activityPreviewUpdate = useActivityPreviewUpdate();

    const closePeekPanel = () => {
        let section_ele = document.querySelector("section");
        section_ele.classList.remove("activePanel");
        setPeekActive(false);
    }
    
    const openPeekPanel = (e) => {

        activityPreviewUpdate(e.currentTarget.id);

        let section_ele = document.querySelector("section");
        section_ele.classList.add("activePanel");
        setPeekActive(true);
    }

    return (
        <section id="homeView" className="panelView"> 
            <div id="contentArea">
                <ThumbnailGroup name="favorite" data={fakeData} title="Favorited recently" onClick={openPeekPanel} />
            </div>
            {peekActive && <PanelPreview onClosePanel={closePeekPanel} />}
            
        </section>
    );
};

export default HomeView;

At the moment I am only printing the ID in the side panel.

import React, { useState } from 'react';
import { NavLink, useHistory } from 'react-router-dom';
import Card from './Card';
import Icon from './Icon';
import { useActivityPreview, ActivityPreviewProvider } from '../context/ActivityPreviewContext';

const PanelPreview = (props) => {
    //hooks
    const history = useHistory();
    const activityPreview = useActivityPreview();

    return (
        <Card id="panelPreview">
          <div className="panelHeader">
            {
                <p>{activityPreview}</p>
            }   
          </div>
        </Card>
    );
};

export default PanelPreview;

解决方案

It's because React doesn't render JSON in HTML, only strings. e.currentTarget.id renders that string and [1,2,3] is joined and rendered as 123.

If you plan on accepting an object, you should consider selecting that property in the p element. <p>{activityPreview.a}</p> would display123 without errors.

Although JSON.Stringify({a:123, b:456}) might be what you're looking for, to display the entire object as-is, without breaking.

这篇关于使用 React useContext() 钩子传递对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆