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

时间:2019-05-18 18:54:44

标签: javascript reactjs react-context

React文档说,如果您打算从嵌套组件更新上下文,则将Root组件中定义的功能作为道具传递给子组件。

我已经实现了相同的方法:

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 App,用于学习Context API。我要实现的目标是在updateGreet()组件内定义GreetButton方法,而不是在App组件内定义方法,因为该功能与{{1}没有关系}组件。

我看到的另一个优点是,如果我选择完全删除App组件,则无需跟踪它在另一个组件中定义的所有方法。

有没有办法实现这一目标?

1 个答案:

答案 0 :(得分:1)

我认为updateGreet方法确实与App有关,因为它正在处理App状态。

我不认为这是特定于上下文的问题,而是将功能向下传递给子组件的正常反应。

要实现您的愿望,您可以可以绑定并将App的{​​{1}}方法传递给提供者,然后在{{1}中实现setState }组件,但这将是一种反模式,我不推荐使用。

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

本质上,将updateGreet中的内容实现为其自己的 Provider GreetButton。在App的render方法中,只需使子代通过:

GreetProvider

现在,您的所有问候语逻辑都可以与上下文一起生活在源代码中。在GreetProvider中使用新的render() { return ( <DataContext.Provider value={ this.state }> { this.props.children } </DataContext.Provider> ) } 类,其任何子类都可以使用其方法。