【问题标题】:How do I add a JS state variable of 1 React component for use in other components?如何添加 1 个 React 组件的 JS 状态变量以用于其他组件?
【发布时间】:2021-12-29 11:52:20
【问题描述】:

我有一个 Home.js 组件,它让用户注册 API 并登录,然后获取从响应授权标头接收到的令牌并将其保存在 state 'token' 变量中。

此令牌将在所有其他组件中用于在发出请求时访问 API,那么将此值用于所有其他组件的最佳方式是什么?

Home.js:

   const SIGNUP_URL = 'http://localhost:8080/users/signup';
    const LOGIN_URL = 'http://localhost:8080/login';
    class Home extends Component {
    
        constructor(props) {
            super(props);
            this.state = {
                isAuthenticated:false,
                token: ''
            };
        }
        
        componentDidMount() {
            const payload = {
                "username": "hikaru",
                "password": "JohnSmith72-"
            };
            fetch(SIGNUP_URL, {
                method: 'POST',
                headers: {
                    "Accept": "application/json",
                    "Content-Type": "application/json"
                },
                body: JSON.stringify(payload)
            })
                .then(response => response.json())
                .then((data) => {
                    console.log(data);
                });
            fetch(LOGIN_URL, {
                method: 'POST',
                headers: {
                    "Accept": "application/json",
                    "Content-Type": "application/json"
                },
                body: JSON.stringify(payload)
            })
                .then(response =>
                    this.setState({token: response.headers.get("Authorization"), isAuthenticated:true})
                )
    
        }

例如 userList 组件将从 API 中获取用户数据,但需要存储在 Home 组件的令牌状态变量中的 API 令牌才能通过授权标头成功发送请求。

感谢您的帮助

【问题讨论】:

    标签: javascript reactjs json react-native request


    【解决方案1】:

    例如,您可以创建一个名为 authenticated_request 的自定义函数。这个函数可以从 CookieStorage 中获取你的令牌,如果是 web 或者异步存储,如果是 react-native 或者即使你有它在一些状态管理库中。没关系。使用此函数而不是 fetch 函数并在其中调用 fetch。将其视为您的网络请求的高阶函数。

    const authenticated_request(url, config) {
      fetch(url, {
        ...config,
        headers: {
          ...config.headers,
          Authorization: getToken()
        }
      });
    }
    

    您还可以利用 axios 之类的东西,并使用请求拦截器来拦截请求和响应。根据需要注入您的令牌。

    【讨论】:

      【解决方案2】:

      您应该使用 AuthContext 和 localStorage 来执行此操作,将令牌保存在 state 或 localStorage 中,并制作一个配置文件,在调用我在 axios 中完成的 api 时使用相同的令牌。 Axios 有一个拦截器的概念,它允许我们将令牌附加到我们的 api 调用,我在成功登录后将令牌保存在 localStorage 中,然后使用 localStorage 中的相同令牌添加到需要令牌的每个调用,如果 api 不需要一个token(有些api可以是公开的)我可以直接用axios,看看下面的代码:

      import axios from 'axios';
      
      let apiUrl = '';
      let imageUrl = '';
      if(process.env.NODE_ENV === 'production'){
          apiUrl = `${process.env.REACT_APP_LIVE_URL_basePath}/web/v1/`;
      }else{
         apiUrl = `http://127.0.0.1:8000/web/v1/`;
      }
      
      const config = {
          baseURL: apiUrl,
          headers: {
              'Content-Type': 'application/json;charset=UTF-8',
              "Access-Control-Allow-Origin": "https://www.crazyforstudy.com",
              'Access-Control-Allow-Methods': 'GET, POST, PATCH, DELETE',
          },
      };
      
      const authAxios = axios.create(config);
      
      authAxios.interceptors.request.use(async function(config) {
          config.headers.Authorization = localStorage.getItem('access_token') ?
              `Bearer ${localStorage.getItem('access_token')}` :
              ``;
          return config;
      });
      
      export { apiUrl, axios, authAxios };
      

      现在在进行 api 调用时,您可以执行以下操作:

      import { apiUrl, authAxios } from '../config/config'
      
      export async function saveAssignment(data) {
          try {
              const res = await authAxios.post(apiUrl + 'assignment/save-assignment', data)
              return res.data;
          }
          catch(e){
              
          }
      }
      

      这里注意我不是使用 axios 进行 api 调用,而是使用 authAxios 进行调用(从配置文件中导出),这将在标头中有令牌。

      (您也可以使用 Redux 等第三方库,但概念保持不变)

      【讨论】:

        【解决方案3】:

        您需要一个集中的状态,这就是 状态管理 库的用途。您可以使用 Redux 等第三方库,也可以直接使用 React 自己的 context。你可以在 google 上搜索 React 的状态管理,你会发现很多有用的资源

        【讨论】:

          【解决方案4】:

          如果您的应用是 SSR,您可以将令牌放入 cookie。为此,您必须创建以下函数:

          export const eraseCookie = (name) => {
              document.cookie = `${name}=; Max-Age=-99999999;`;
          };
          
          export const getCookie = (name) => {
              const pairs = document.cookie.split(';');
              const pair = pairs.find((cookie) => cookie.split('=')[0].trim() === name);
              if (!pair) return '';
              return pair.split('=')[1];
          };
          
          export const setCookie = (name, value, domain) => {
              if (domain) {
                  document.cookie = `${name}=${value};path=/`;
              } else {
                  document.cookie = `${name}=${value}`;
              }
          };
          

          您也可以将令牌放入本地存储:

          通过内置函数设置到本地存储:

          localStorage.setItem('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c');
          

          通过内置函数获取令牌:

          const token = localStorage.getItem('token');
          

          【讨论】:

            猜你喜欢
            • 2017-07-14
            • 1970-01-01
            • 2020-12-25
            • 1970-01-01
            • 2018-10-20
            • 2018-02-24
            • 2019-09-29
            • 1970-01-01
            • 2020-12-14
            相关资源
            最近更新 更多