程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了将带有 React Context API 的函数传递给嵌套在树深处的子组件以更新状态值大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决将带有 React Context API 的函数传递给嵌套在树深处的子组件以更新状态值?

开发过程中遇到将带有 React Context API 的函数传递给嵌套在树深处的子组件以更新状态值的问题如何解决?下面主要结合日常开发的经验,给出你关于将带有 React Context API 的函数传递给嵌套在树深处的子组件以更新状态值的解决方法建议,希望对你解决将带有 React Context API 的函数传递给嵌套在树深处的子组件以更新状态值有所启发或帮助;

我第一次使用 React Context API。我有一个 JWT 令牌生成器,它接受标头、有效载荷和秘密的输入。虑到这一点,JWT 生成器组件嵌套在几个不同的组件中。生成 JWT 后,我想更新应用程序,以便在所有不同的页面中都可以使用 JWT。

基于之前的工作,我尝试使用各种形式的 React Context 来实现这一点,但是在尝试将一种“setJWT”函数传递给 JWT 生成器以便更新此状态值时,我特别遇到了问题当用户成功通过身份验证时。

App.tsx(父)

export default class App extends Component<AppProps> {
  constructor(props: AppProps) {
    super(props);
    this.state = {};
  }

  render(): JsX.Element {
    // const { user } = this.state;

    return (
      <>
        <browserRouter>
          <header />
          <Box classname="root">
            <div style={{ display: 'flex' }}>
              <Box classname="nav">
                <Navbar headings={headings} subheadings={subheadings} />
              </Box>
              <Box
                style={{
                  marginleft: '210px',margintop: '50px',position: 'fixed',}}
              >
                <Content />
              </Box>
            </div>
          </Box>
        </browserRouter>
      </>
    );
  }
}

Authentication.tsx(子)

export interface PaneProps {
  headings: {
    key: number;
    name: String;
    pathname: String;
  }[];
  subheadings: {
    key: number;
    name: String;
    calls: String[];
  }[];
}

interface PageState {
  isLoggedIn: Boolean;
}

export default class Authentication extends Component<unkNown,PageState> {
  constructor(props: PaneProps) {
    super(props);
    this.state = {
      isLoggedIn: true,};
  }

  render(): JsX.Element {
    const { isLoggedIn } = this.state;
    return (
      <>
        <Box classname="outer-Box">
          <GrID container classname="grID-container">
            <div classname="some-page-wrapper">
              <div classname="row">
                <div classname="column">
                  <div classname="text-column">
                    <Authenticationtext />
                  </div>
                </div>

                {(function () {
                  if (isLoggedIn) {
                    return (
                      <div classname="column">
                        <div classname="text-column">
                          <div classname="sticky-div-bs">
                            <JWTGenerator />
                          </div>
                        </div>
                      </div>
                    );
                  }
                  return (
                    <div classname="column">
                      <div classname="bs-column">
                        <div classname="sticky-div-bs">
                          <iframeBS />
                        </div>
                      </div>
                    </div>
                  );
                })()}
              </div>
            </div>
          </GrID>
        </Box>
      </>
    );
  }
}

JWTGenerator.tsx (child-child)

export interface AppProps {
  headings?: {
    key: number;
    name: String;
    pathname: String;
  }[];
  subheadings?: {
    key: number;
    name: String;
    calls: String[];
  }[];
}

interface AppState {
  header: String;
  payload: String;
  secret: String;
  textAreaValue?: String;
}

export default class JWTGenerator extends Component<AppProps,AppState> {
  constructor(props: AppProps) {
    super(props);
    this.state = {
      header: JsON.Stringify(
        {
          alg: 'HS256',typ: 'JWT',},null,2,),payload: JsON.Stringify(
        {
          iat: 1501768003,iss: 'perioDicdev',sub: 'perioDicadmin',secret: '',textAreaValue: '',};
    this.onChangeheader = this.onChangeheader.bind(this);
    this.onChangePayload = this.onChangePayload.bind(this);
    this.onChangeSecret = this.onChangeSecret.bind(this);
  }

  onChangeheader(newheader: String): voID {
    this.setState({ header: newheader });
  }

  onChangePayload(newPayload: String): voID {
    this.setState({ payload: newPayload });
  }

  onChangeSecret(newSecret: String): voID {
    this.setState({ secret: newSecret });
  }

  onChangeTextArea(header: String,payload: String,secretKey: String): voID {
    const cleanheader = btoa(header.replace(/\s/g,''));
    const cleanPayload = btoa(payload.replace(/=/g,'').replace(/\s/g,''));
    const basemessage = `${Cleanheader}.${CleanPayload.replace(/=/g,'')}`;
    const secret = CryptoJs.HmacSHA256(basemessage,secretKey)
      .toString(CryptoJs.enc.base64)
      .replace(/=/g,'')
      .replace(/\+/g,'-')
      .replace(/\//g,'_');
    this.setState({
      textAreaValue: `${Cleanheader}.${CleanPayload.replace(
        /=/g,'',)}.${secret}`,});
  }

  render(): JsX.Element {
    const { header,payload,secret,textAreaValue } = this.state;
    return (
      <>
        <div classname="main-container-jwt">
          <div classname="top-block-jwt">
            <Box classname="top-bar-text-jwt">
              <i classname="white">Example Call</i>
            </Box>
          </div>

          <div classname="example-block-jwt">
            <div classname="header-example-jwt">
              <AceEditor
                placeholder="header"
                value={header}
                onChange={(E) => this.onChangeheader(E)}
                oninput={(e: any) =>
                  this.onChangeTextArea(header,secret)
                }
                // mode="Json"
                theme="xcode"
                name="ace-editor"
                FontSize={11}
                showPrintmargin
                wrapEnabled
                showGutter
                setoptions={{
                  highlightGutterline: false,highlightActiveline: false,enableBasicautocompletion: true,enableliveautocompletion: true,enableSnippets: false,showlinenumbers: false,tabSize: 2,useWorker: false,}}
                style={{
                  color: 'red',position: '@R_419_4614@',wIDth: '100%',height: '100%',maxHeight: '100px',}}
              />
            </div>
            <div classname="payload-example-jwt">
              <AceEditor
                placeholder="Payload"
                value={payloaD}
                onChange={(e: any) => this.onChangePayload(E)}
                oninput={(e: any) =>
                  this.onChangeTextArea(header,}}
                style={{
                  color: 'blue',}}
              />
            </div>
            <div classname="secret-example-jwt">
              <AceEditor
                placeholder="Secret"
                value={secret}
                onChange={(e: any) => this.onChangeSecret(E)}
                oninput={(e: any) =>
                  this.onChangeTextArea(header,}}
                style={{
                  color: 'green',}}
              />
            </div>

            <div classname="spacer">
              <button
                // onClick={() =>
                //   this.setState((prev) => ({
                //     ...prev,//     textAreaValue: prev.value,//   }))
                // }
                onClick={(e: any) =>
                  this.onChangeTextArea(header,secret)
                }
                classname="try-it-button"
                style={{
                  BACkgroundcolor: '#533cf8',color: 'white',borderRadius: 0,FontSize: 13,FontWeight: 200,}}
              >
                Make Call
              </button>
              <div classname="spacer-text-div">
                auto-update 'fat',Alphabetize payload,and make the example
                call above
              </div>
            </div>

            <div classname="header-2-jwt">
              <i classname="white">Example Response</i>
            </div>

            <div classname="textarea-example-jwt">
              <AceEditor
                // placeholder="Enter a call here..."
                value={textAreaValue || ''}
                Readonly
                // mode="Json"
                theme="twilight"
                name="ace-editor"
                FontSize={11}
                showPrintmargin
                wrapEnabled
                setoptions={{
                  highlightGutterline: false,indentedSoftWrap: false,wrapEnabled: true,}}
                style={{
                  position: '@R_419_4614@',}}
              />
            </div>

            <div classname="bottom-block-jwt" />
          </div>
        </div>
      </>
    );
  }
}

我需要做的是在整个应用程序中传递这个 jwt 令牌,以确保 API 用户的身份验证。非常感谢任何建议/帮助。谢谢。

解决方法

为此,您需要在应用的顶层初始化一些状态以设置 JWT。当然,这个状态一开始会是null,因为正如你所说,你需要将JWT设置为几个子级。但是由于上下文 API 的工作原理,您仍然需要在顶部对其进行初始化才能使用 Context API。

首先创建一些用户上下文:

import { createContext } from 'react'; 

export const UserContext = createContext(null);

然后在 App.js 中创建一些状态并将其放入上下文中,以便将其传递给将更新 JWT 的子级。请务必从 useState 传递 setJwt 函数。

const [jwt,setJwt] = useState(null);

    return (
     <UserContext.Provider value={{ jwt,setJwt }}>
        <BrowserRouter>
          <Header />
          <Box className="root">
            // etc. your app here
          </Box>
        </BrowserRouter>
     </UserContext.Provider>)

然后您可以通过从上下文中检索它来访问 JWTGenerator.tsx(child-child)中的该函数。

const { setJwt } = useContext(UserContext)

这将允许您在此子项中设置 JWT。并且因为 JWT 也在上下文中传递,一旦它在 JWTGenerator.tsx 中更新,该状态值就可以在任何其他子组件中访问。

这里详细解释了如何使用此模式在上下文中设置用户,尽管在此示例中用户设置在顶级,但它仍然是相同的模式:https://jawblia.medium.com/react-template-for-jwt-authentication-with-private-routes-and-redirects-f77c488bfb85 我还需要参 React 文档当然,Ben Awad 在 YouTube 上有一个关于此的视频教程。

大佬总结

以上是大佬教程为你收集整理的将带有 React Context API 的函数传递给嵌套在树深处的子组件以更新状态值全部内容,希望文章能够帮你解决将带有 React Context API 的函数传递给嵌套在树深处的子组件以更新状态值所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。