Giu*_*age 5 javascript reactjs react-native
当谈到状态集中化时,我知道如何使用 context api 和 Redux。但要恢复该状态,我们始终必须位于反应组件内。
访问不在反应组件内部的公共函数内的全局状态/变量的最佳策略是什么?
在环境变量中不是一个选项,因为该值在应用程序运行后会更改。出于安全原因,我不想放入 cookie 或本地存储。
索引.ts
import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloProvider } from 'react-apollo';
import apolloClient from './services/apollo';
import { PersonalTokenProvider } from './providers/personal-token';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<PersonalTokenProvider>
<ApolloProvider client={apolloClient}>
<App />
</ApolloProvider>
</PersonalTokenProvider>
</React.StrictMode>,
document.getElementById('root'),
);
Run Code Online (Sandbox Code Playgroud)
PresonalToken 上下文提供者
import React, { useState } from 'react';
interface ProviderProps {
children: JSX.Element[] | JSX.Element;
}
export const PersonalTokenContext = React.createContext({});
export const PersonalTokenProvider: React.FC<ProviderProps> = (
props: ProviderProps,
) => {
const [token, setToken] = useState<string | null>(null);
const { children } = props;
return (
<PersonalTokenContext.Provider value={{ token, setToken }}>
{children}
</PersonalTokenContext.Provider>
);
};
Run Code Online (Sandbox Code Playgroud)
阿波罗客户端配置
import { useContext } from 'react';
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { PersonalTokenContext } from '../providers/personal-token';
//cant do this
const {token} = useContext(PersonalTokenContext)
const httpLink = new HttpLink({
uri: 'https://api.github.com/graphql',
headers: {
authorization: `Bearer ${token}`,
},
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
});
export default client;
Run Code Online (Sandbox Code Playgroud)
有多种方法可以模拟单例以从 React 中管理 Apollo 客户端。这是一种useRef在进行 GraphQL 查询时始终拥有最新令牌并且useMemo仅创建客户端一次的方法。
import {
ApolloClient,
createHttpLink,
InMemoryCache,
ApolloProvider
} from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
// The name here doesn't really matters.
export default function CustomApolloProvider(props) {
const { token } = useContext(PersonalTokenContext);
const tokenRef = useRef();
// Whenever the token changes, the component re-renders, thus updating the ref.
tokenRef.current = token;
// Ensure that the client is only created once.
const client = useMemo(() => {
const authLink = setContext((_, { headers }) => ({
headers: {
...headers,
authorization: tokenRef.current ? `Bearer ${tokenRef.current}` : '',
}
}));
const httpLink = createHttpLink({
uri: 'https://api.github.com/graphql',
});
return new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
}, [])
return <ApolloProvider client={client} {...props} />;
}
Run Code Online (Sandbox Code Playgroud)
然后在应用程序中:
<PersonalTokenProvider>
<CustomApolloProvider>
<App />
</CustomApolloProvider>
</PersonalTokenProvider>
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
Apollo文档建议使用本地存储来管理身份验证令牌。
Run Code Online (Sandbox Code Playgroud)import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; const httpLink = createHttpLink({ uri: '/graphql', }); const authLink = setContext((_, { headers }) => { // get the authentication token from local storage if it exists const token = localStorage.getItem('token'); // return the headers to the context so httpLink can read them return { headers: { ...headers, authorization: token ? `Bearer ${token}` : "", } } }); const client = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache() });
优点:
缺点:
在模块的根部使用一个简单的变量就足够了,您甚至不再需要令牌上下文。
import {
ApolloClient,
createHttpLink,
InMemoryCache,
makeVar
} from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
// module scoped var for the token:
let token;
// custom module setter:
export const setToken = (newToken) => token = newToken;
const httpLink = createHttpLink({
uri: '/graphql',
});
// Apollo link middleware gets called for every query.
const authLink = setContext((_, { headers }) => ({
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
}
}
));
export const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
juanireyes建议使用Apollo Reactive 变量,但它们适用于特定的用例,完全没有必要像我们在这里想要的那样全局管理令牌。它与上面的模块范围变量建议类似,但有额外的步骤。
| 归档时间: |
|
| 查看次数: |
2159 次 |
| 最近记录: |