使用 React useContext() 钩子传递对象

时间:2021-01-29 01:48:44

标签: reactjs react-hooks

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

这是我写的上下文文件

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

}

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

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

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';
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;

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

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;

1 个答案:

答案 0 :(得分:0)

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

如果您打算接受一个对象,您应该考虑在 p 元素中选择该属性。 <p>{activityPreview.a}</p> 会正确显示123

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