如何添加 1 个 React 组件的 JS 状态变量以用于其他组件?

Posted

技术标签:

【中文标题】如何添加 1 个 React 组件的 JS 状态变量以用于其他组件?【英文标题】:How do I add a JS state variable of 1 React component for use in other components? 【发布时间】: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 令牌才能通过授权标头成功发送请求。

感谢您的帮助

【问题讨论】:

【参考方案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】:

如果您的应用是 s-s-r,您可以将令牌放入 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');

【讨论】:

以上是关于如何添加 1 个 React 组件的 JS 状态变量以用于其他组件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React.js 的另一个组件中更新组件状态变量的值?

React 应用程序变慢并且 JS Heap 变大。如何发现内存泄漏?

如何在 react.js 中跨子组件持久化数据或状态?

React.js:在更改状态的输入字段中单击取消时如何返回先前的状态值[重复]

如何向 React/MUI 自动完成组件添加唯一键?

如何使用 React.JS 正确验证输入值?