反应上下文装饰器/用户?

时间:2018-11-20 19:29:50

标签: javascript reactjs

编辑:也许可以将其称为上下文订户?

我什至不确定这是否是我要实现的正确概念。我希望能够创建一个可以完成肮脏工作的组件,并且只需将上下文附加到可以使用的组件上即可。

我试图找到没有运气的类似东西,这使我相信我没有想到我在做什么的正确的 literal 上下文...

我尝试过这样的事情:

import React, { Component } from "react";
export const Context = React.createContext();

export class ContextProvider extends Component {
state = {
    scanning: false
};

render() {
    return (
        <Context.Provider
            value={{
                state: this.state,
                handleClick: () => this.setState({
                    scanning: !this.state.scanning
                })
            }}
        >
            {this.props.children}
        </Context.Provider>
    );
}
}

我试图使其与此一起工作。

import React from "react";
import { Context } from "./Context";

const WithContext = (children) => (props) => {
    return (
        <Context.Consumer>
            { state  => (<children {...props} context={state} />) }
        </Context.Consumer>
    )
};

然后与...一起食用

...
<WithContext>
    <MyComponent />
</WithContext>
...

但是,这似乎失败了,或者说我要返回的是函数而不是react组件。

2 个答案:

答案 0 :(得分:1)

您的WithContext组件将无法正常工作...它必须是一个与render函数具有相同功能的函数。像这样:

import React from "react";
import { Context } from "./Context";

const WithContext = ({ children, ...props }) => (
  <Context.Consumer>{state  => React.Children.map(children, (child) => (
    React.cloneElement(child, { context: state }) 
  ))}</Context.Consumer>
);

请注意,我们使用withContextdocs)遍历React.Children.map个孩子的每个直接孩子,并通过使用{{1} }(docs)。这样可以保留子组件的原始属性,然后将其浅层合并到传递给函数的第二个参数中。

答案 1 :(得分:-1)

您的代码中使用上下文存在一些小错误...这是一个完整的示例...

比方说,我们有一个结构,其中有App.js -> Parent.js -> Child.js个组件...我们希望通过上下文API而不是通过道具将数据从App传递到从App到Parent到Child,而避免了prop钻探和孩子直接使用数据...

这是什么样子:

context.js:

import React from 'react';

const Context = React.createContext();

export class Provider extends React.Component {
  state = { name: 'Bob', age: 20 };

  handleGrowUp = () => {
    this.setState({ age: this.state.age + 1 });
  };
  render() {
    return (
      <Context.Provider
        value={{
          state: {
            ...this.state,
          },
          actions: {
            growUp: this.handleGrowUp,
          },
        }}
      >
        {this.props.children}
      </Context.Provider>
    );
  }
}

export const Consumer = Context.Consumer;

App.js:

import React from 'react';
import Parent from './Parent';

import { Provider } from './context';

const App = () => (
  <Provider>
    <Parent />
  </Provider>
);

export default App;

Parent.js:

import React from 'react';
import Child from './Child';

const Parent = () => (
  <div>
    <Child />
  </div>
);

export default Parent;

Child.js:

import React from 'react';
import { Consumer } from './context';

const Child = () => (
  <div>
    <Consumer>
      {value => (
        <div>
          <p>{value.state.name}</p>
          <p>{value.state.age}</p>
          <button onClick={value.actions.growUp}>Grow Up</button>
        </div>
      )}
    </Consumer>
  </div>
);

export default Child;

这是一个有效的演示:https://codesandbox.io/s/9z06xzlyly