通过函数将道具传递给全局上下文提供者

时间:2019-07-30 07:26:26

标签: javascript reactjs typescript

我希望获得帮助,以了解如何从props组件的function内部将child传递给上下文提供程序。

我有一个全局提供程序,我想从表单中保存data,如果error失败,则要保存onSubmit数据。

使用createContext我有一家全球服务提供商

import React, { createContext } from 'react';

interface InterfaceProps {
  children?: any;
}

interface InterfaceState {
  error: any;
  toggleAuthError: any;
}

const GlobalContext = createContext({
  error: null,
  toggleAuthError: () => {}
});

export class GlobalProvider extends React.Component<InterfaceProps, InterfaceState> {
  public toggleAuthError = ({ authError }: any) => {
    this.setState({ error: authError });
  };

  public state = {
    error: null,
    toggleAuthError: this.toggleAuthError
  };

  public render() {
    const { children } = this.props;
    return <GlobalContext.Provider value={this.state as any}>{children}</GlobalContext.Provider>;
  }
}

export const GlobalConsumer = GlobalContext.Consumer;

然后在表单child组件中,我有一个名为onSubmit的函数。

public handleFormSubmit = async (data: { email: string; password: string }) => {
    const { form } = this.props;
    const { email, password } = data;

    await form
      ...
      .catch((error: any) => {
        toggleAuthError(error); // Want this to trigger the function and pass error to the context provider
        this.setState({
          loading: false
        });
      });
  };

如何在上下文提供程序中将error传递给this.toggleAuthError

2 个答案:

答案 0 :(得分:1)

您应该使用GlobalConsumer包装您的子组件,以便访问上下文值。像这样:

<MyContext.Consumer>
  {({toggleAuthError}) => /* render something based on the context value */}
</MyContext.Consumer>

然后,您只需将toggleAuthError传递到handleFormSubmit函数。

答案 1 :(得分:1)

如Ovidiu所指出的,如果您的组件是功能组件,那么使用Context.Consumer很好。

但是,如果您的组件扩展了React.Component,则可以使用Context.contextType。这样,您就可以使用this.context来消耗该Context类型的最近值。

使用此设置,您可以在回调函数中访问toggleAuthError方法。

对于您的情况,在child组件(如果是Class)中,您将使用:

static contextType = GlobalContext;

,然后可以使用toggleAuthError访问this.context.toggleAuthError方法。

以下示例显示了两种方法-Context.contextTypeContext.Consumer来使用上下文的两个部分(errortoggleAuthError)。

const GlobalContext = React.createContext({
  error: 0,
  toggleAuthError: () => {}
});

class GlobalProvider extends React.Component {
  constructor(props) {
    super(props);
    this.toggleAuthError = (newError) => {
      this.setState(state => ({
        error: newError
      }))
    };
    
    this.state = {
      error: 0,
      toggleAuthError: this.toggleAuthError,
    };
  }
  
  render() {
    return (
      <GlobalContext.Provider value={this.state}>
        {this.props.children}
      </GlobalContext.Provider>
    )
  }
}

const Form = () => {
  return (
    <div>
      <ToggleAuthErrorButton />
      <Error />
    </div>
  )
}

// A React component which uses context using Context.contextType
class ToggleAuthErrorButton extends React.Component {
  static contextType = GlobalContext;
  
  toggleError = () => {
    return this.context.toggleAuthError(this.context.error + 1);
  }
  
  render() {
    return (
      <button onClick={this.toggleError}>Toggle Auth Error</button>
    )
  }
}

// A function component which uses context using Context.Consumer
const Error = () => {
  return (
    <GlobalContext.Consumer>
      {({error}) => {
        return (
          <div>Error {error}</div>
        )
      }}
    </GlobalContext.Consumer>
  )
}

class App extends React.Component {
  render(){
    return (
      <GlobalProvider>
        <Form />
      </GlobalProvider>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>