我正在使用 lerna 创建一个 monorepo,其中我有一个这样的结构:
root
packages
application - Our root application
components - Just some react components, that are to be used by the application
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是我正在使用 Material-UI 及其主题功能,在应用程序根目录中,我们将有一个 ThemeProvider:
import { ThemeProvider } from '@material-ui/styles';
//...
function App() {
return (
<ThemeProvider theme={theme}>
<MyMaterialComponent/>
</ThemeProvider>
);
}
Run Code Online (Sandbox Code Playgroud)
然后在库组件中,我们使用主题,在我们的例子中使用makeStyles钩子。
import React from 'react';
import { makeStyles } from '@material-ui/styles';
import Card from "@material-ui/core/Card";
const useStyles = makeStyles(theme => {
console.log(theme); //When this component doesn't have …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个 UserContext 以便 React 应用程序中的所有类组件都可以访问。我收到以下错误。
ReferenceError: Cannot access 'UserContext' before initialization
Run Code Online (Sandbox Code Playgroud)
应用程序.js
import React, { createContext } from 'react';
export const UserContext = createContext(null);
function App() {
return (
<div className="App">
<UserContext.Provider value={null}>
<PageRoutes />
</UserContext.Provider>
</div>
);
}
export default App;
Run Code Online (Sandbox Code Playgroud)
登录页面.js
import React, { Component } from 'react';
import { UserContext } from './App';
class MasterLoginPage extends Component {
static contextType = UserContext;
constructor(props) {
super(props);
this.state = {
username: null,
loggedIn: false
}
// logic to work …Run Code Online (Sandbox Code Playgroud) 我有一个相当复杂的上下文,我将其包装在我的应用程序中来处理身份验证并提供从身份验证服务检索到的关联数据。我想绕过提供程序的所有功能并仅模拟返回值。当上下文呈现时,它会执行一堆我在测试时不希望发生的初始化函数。
我在我的包装函数中尝试了类似的方法:
const mockValue = {
error: null,
isAuthenticated: true,
currentUser: 'phony',
login: jest.fn(),
logout: jest.fn(),
getAccessToken: jest.fn(),
}
const MockAuthContext = () => ( React.createContext(mockValue) )
jest.mock("../contexts/AuthContext", () => ({
__esModule: true,
namedExport: jest.fn(),
default: jest.fn(),
}));
beforeAll(() => {
AuthContext.mockImplementation(MockAuthContext);
});
const customRender = (ui, { ...renderOpts } = {}) => {
const ProviderWrapper = ({ children }) => (
<AuthContext.Provider>
{children}
</AuthContext.Provider>
);
return render(ui, { wrapper: ProviderWrapper, ...renderOpts });
};
// re-export everything
export * from …Run Code Online (Sandbox Code Playgroud) 我正在寻找在反应中使用全局屏幕加载器的解决方案。
我不太熟悉反应上下文,但我想知道这是否可以帮助我。基本上我正在介绍一个屏幕加载器,我想也许最好的方法是在主要组件中的某个地方有一个全局加载器。所以得出结论:
那么有没有一种方法可以拥有 loader/loaderText 的全局状态,并在需要时使用上下文进行设置和重置?
如果有一种简单的方法可以做到这一点,那么您认为使用这种解决方案可能有任何缺点吗?也许这有点过分了。
我需要一些帮助,以帮助您了解如何使用来测试应用程序React Context。
这是我的示例设置。
context.js
import React from 'react'
export const AppContext = React.createContext()
Run Code Online (Sandbox Code Playgroud)
App.js
import React from 'react'
import MyComponent from './MyComponent'
import {AppContext} from './context'
const App extends React.Component {
state = {
items: []
}
handleItemAdd = newItem => {
const {items} = this.state
items.push(newItem)
this.setState(items)
}
render() {
return (
<AppContext.Provider value={{
addItem: this.handleItemAdd
}}>
<MyComponent />
</AppContext.Provider>
)
}
}
export default App
Run Code Online (Sandbox Code Playgroud)
MyComponent.js
import React from 'react'
import {AppContext} from './context'
const MyComponent …Run Code Online (Sandbox Code Playgroud) unit-testing reactjs jestjs react-context react-testing-library
我正在使用 React 的上下文 api 来存储一组项目。有一个组件可以通过 useContext() 访问这个数组并显示数组的长度。还有另一个组件可以访问该函数以通过 useContext 更新此数组。将项目添加到数组时,组件不会重新渲染以反映数组的新长度。当我导航到应用程序中的另一个页面时,组件会重新呈现并反映数组的当前长度。每当上下文中的数组发生变化时,我都需要组件重新渲染。
我曾尝试使用 Context.Consumer 而不是 useContext 但是当数组更改时它仍然不会重新呈现。
//orderContext.js//
import React, { createContext, useState } from "react"
const OrderContext = createContext({
addToOrder: () => {},
products: [],
})
const OrderProvider = ({ children }) => {
const [products, setProducts] = useState([])
const addToOrder = (idToAdd, quantityToAdd = 1) => {
let newProducts = products
newProducts[newProducts.length] = {
id: idToAdd,
quantity: quantityToAdd,
}
setProducts(newProducts)
}
return (
<OrderContext.Provider
value={{
addToOrder,
products,
}}
>
{children}
</OrderContext.Provider> …Run Code Online (Sandbox Code Playgroud) 我想添加一个 Loader 组件,以便在React 中进行 API 调用时呈现。我想使用react context + hooks 而不是 redux。
正如反应钩子的规则所说,我们不应该在反应组件之外使用反应钩子。但是我需要在Axios拦截器内部分派SHOW_LOADER和,如下所示。HIDE_LOADER
有没有办法实现这一目标?
import axios from "axios";
axios.interceptors.request.use(
config => {
dispatch({
type: "SHOW_LOADER"
})
return config;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
axios.interceptors.response.use(
response => {
dispatch({
type: "HIDE_LOADER"
})
return response;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
function GlobalLoader(){
const [state,dispatch] = useContext(LoaderContext);
return(
<div>
{
state.loadStatus …Run Code Online (Sandbox Code Playgroud) 有很多文章展示了如何用上下文和钩子替换 Redux(例如,参见Kent Dodds 的这篇文章)。基本思想是通过上下文使您的全局状态可用,而不是将其放在 Redux 存储中。但是这种方法有一个大问题:订阅上下文的组件将在上下文发生任何更改时重新呈现,无论您的组件是否关心刚刚更改的状态部分。对于函数式组件,React-redux 通过useSelector hook解决了这个问题. 所以我的问题是:是否可以创建像 useSelector 这样的钩子,它会抓取一段上下文而不是 Redux 存储,具有与 useSelector 相同的签名,并且就像 useSelector 一样,只会在“选择”部分上下文发生了变化?
(注意:React Github 页面上的这个讨论表明它不能完成)
我已经设置了一个使用 Context 存储页面标题的基本示例项目,但是当我设置它时,组件不会重新呈现。
主要文件:
上下文.js
import React from 'react'
const Context = React.createContext({})
export default Context
Run Code Online (Sandbox Code Playgroud)
AppWrapper.js
import React from 'react'
import App from './App'
import Context from './Context'
function AppWrapper () {
return (
<Context.Provider value={{page: {}}}>
<App />
</Context.Provider>
)
}
export default AppWrapper
Run Code Online (Sandbox Code Playgroud)
应用程序.js
import React, { useContext } from 'react';
import Context from './Context';
import Home from './Home';
function App() {
const { page } = useContext(Context)
return (
<>
<h1>Title: {page.title}</h1>
<Home />
</>
); …Run Code Online (Sandbox Code Playgroud) 我继承了前任所有者广泛使用 React.Context 的代码库。这导致了可能被描述为“上下文地狱”的情况
<AppContextProvider>
<AnotherProvider>
<AgainAnotherProvider configProp={false}>
<TestProvider>
<FooProvider>
<BarProvider configHereAlso={someEnvronmentVar}>
<BazProvider>
<BatProvider>
<App />
</BatProvider>
</BazProvider>
</BarProvider>
</FooProvider>
</TestProvider>
</AgainAnotherProvider>
</AnotherProvider>
</AppContextProvider>;
Run Code Online (Sandbox Code Playgroud)
这感觉像是一种反模式,并且在理解整个应用程序的工作方式方面造成了相当大的认知开销。
我该如何解决?是否可以只使用一个提供程序来处理所有事情?我之前使用 redux-toolkit 和 redux 来管理 React 中的状态。上下文有没有类似的东西?
react-context ×10
reactjs ×10
javascript ×3
jestjs ×2
react-hooks ×2
axios ×1
components ×1
frontend ×1
gatsby ×1
interceptor ×1
lerna ×1
loader ×1
material-ui ×1
mocking ×1
react-props ×1
react-redux ×1
redux ×1
unit-testing ×1
use-context ×1