React Context API,从子组件设置上下文状态,而不是将函数作为 props 传递

React Context API, set context state from Child Components instead of passing functions as props

React 文档说,如果您计划从嵌套组件更新上下文,则将 Root 组件中定义的函数作为 prop 传递给子组件。

我已经实现了同样的:

import React from 'react';

const DataContext = React.createContext();

/**
 * The App.
 */
export default class App extends React.Component {
    constructor() {
        super();

        this.updateGreet = this.updateGreet.bind( this );

        this.state = {
            greet: '',
            updateGreet: this.updateGreet
        }
    }

    updateGreet() {
        this.setState({
            greet: 'Hello, User',
        });
    }

    render() {
        return (
            <DataContext.Provider value={ this.state }>
                <GreetButton />
                <DisplayBox />
            </DataContext.Provider>
        )
    }
}

/**
 * Just a button element. On clicking it sets the state of `greet` variable.
 */
const GreetButton = () => {
    return (
        <DataContext.Consumer>
            {
                ( { updateGreet } ) => {
                    return <button onClick={ updateGreet }>Greet</button>
                }
            }
        </DataContext.Consumer>
    )
}

/**
 * Prints the value of `greet` variable between <h1> tags.
 */
const DisplayBox = () => {
    return (
        <DataContext.Consumer>
            {
                ( { greet } ) => {
                    return <h1>{ greet }</h1>
                }
            }
        </DataContext.Consumer>
    )
}

这是我为学习上下文而创建的一个非常简单的 React 应用程序 API。我想要实现的是在 GreetButton 组件中定义 updateGreet() 方法,而不是在 App 组件中定义它,因为该函数与 App 组件。

我看到的另一个优点是,如果我选择完全删除 GreetButton 组件,那么我就不需要跟踪它使用的所有定义在另一个组件中的方法。

我们有什么办法可以做到这一点吗?

我认为updateGreet方法确实App有关,因为它正在操纵App状态。

我不认为这是一个 context-specific 问题,而是将函数向下传递给 child 组件的正常反应实践。

为了实现您的愿望,您可以 绑定 AppsetState 方法并将其传递给提供者,然后在 updateGreet 中实现GreetButton 组件,但那将是一个 anti-pattern,我不推荐它。

当我使用上下文时 API 我通常在一个单独的文件中定义我的上下文并实现一个自定义提供程序以满足我的需要,向下传递相关的方法和属性并在整个树中使用它们作为需要。

基本上,将 App 中的内容实现为自己的 Provider class GreetProvider。在 GreetProvider 的渲染方法中,只需将 children 传递给:

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

现在,您所有的问候语逻辑都可以在源头与上下文共存。在 App 中使用你的新 GreetProvider class,它的任何 children 都将能够使用它的方法。