简体   繁体   English

将路径参数传递给 React 上下文提供程序

[英]Passing path parameter to a React context provider

I have a React context that provides "project" information to child components, and I'd like the keep all things related to project data contained within the context class.我有一个 React 上下文,它为子组件提供“项目”信息,并且我希望保留与上下文类中包含的项目数据相关的所有内容。 An example of this is the "refreshProject" function that retrieves project information from the server.这方面的一个示例是从服务器检索项目信息的“refreshProject”函数。 The challenge is: how to pass the projectID, which is a URL param, into the context class?挑战是:如何将作为 URL 参数的 projectID 传递到上下文类中? In the code below, I currently pass it into the refresh function itself, which means that all child components that want to call refreshProject need to pull the ID from the URL, which is clumsy.在下面的代码中,我目前将其传递给refresh函数本身,这意味着所有要调用refreshProject的子组件都需要从URL中提取ID,这很笨拙。 I can think of several approaches to this but I'm curious what would be considered best-practice here.我可以想到几种方法,但我很好奇这里被认为是最佳实践。

This is the wrapped route with the project ID contained within the URL:这是 URL 中包含项目 ID 的包装路由:

<Switch>
    [other routes here]

    <ProjectContextProvider>
        <AuthenticatedRoute path="/project/:id" exact component={Project} props={childProps} />
    </ProjectContextProvider>
</Switch>

And the ProjectContextProvider class looks like: ProjectContextProvider 类如下所示:

import React, { Component, createContext } from 'react';
import { API } from '../Services'

export const ProjectContext = createContext();

export class ProjectContextProvider extends Component {
    constructor(props) {
        super(props);

        this.refresh = this.refresh.bind(this);

        this.state = {
            project: null,
            refreshProject: this.refresh
        }
    }

// This is what I have
    refresh(projectID) {
        API.getProject(projectID).then(project => {
            this.setState({ project });
        });
    }

// This is what I want
//    refresh() {
//        API.getProject(this.projectID).then(project => {
//            this.setState({ project });
//        });
//    }

    render() {
        return (
            <ProjectContext.Provider value={{...this.state}}>
                {this.props.children}
            </ProjectContext.Provider>
        );
    }
}

The challenge is: how to pass the projectID , which is a URL param, into the context class?挑战是:如何将作为 URL 参数的 projectID 传递到上下文类中?

Of course by context :当然根据上下文

    this.state = {
        projectID: null,
        project: null,
        refreshProject: this.refresh
    }

all child components that want to call refreshProject need to pull the ID from the URL所有想要调用 refreshProject 的子组件都需要从 URL 中拉取 ID

not true , it can be read from router (props location etc.)不正确,它可以从路由器(道具位置等)读取

Make context provider outer to router (routes should be a switch direct children)将上下文提供程序设置为路由器外部(路由应该是交换机直接子项)

<ProjectContextProvider>
  <Switch>
    [other routes here]
    <AuthenticatedRoute path="/project/:id" exact component={Project} props={childProps} />
  </Switch>
</ProjectContextProvider>

Pass state directly to provider, without spreading (it creates a new object, we want to pass a ref)将状态直接传递给提供者,无需传播(它创建了一个新对象,我们要传递一个引用)

<ProjectContext.Provider value={this.state}>
  {this.props.children}
</ProjectContext.Provider>

In <Project/> just mutate directly (usually not advised) projectID in context (not using setState , change not propagated, dependants not rerendered) this.context.projectID = someID;<Project/> ,在上下文中直接改变(通常不建议) projectID (不使用setState ,不传播更改,不重新渲染依赖项) this.context.projectID = someID; (id from router props), then call this.context.refreshProject() - it's binded then it can use this.state.projectID to make API request. (id from router props),然后调用this.context.refreshProject() - 它被绑定然后它可以使用this.state.projectID来发出 API 请求。 When done updated context (with setState) will force rerenderings (of context connected components).完成后,更新的上下文(使用 setState)将强制重新渲染(上下文连接的组件)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM