React 16.3.0已经发布,Context API不再是实验性功能.Dan Abramov(Redux的创建者)在这里写了一篇很好的评论,但是当Context仍然是一个实验性功能已经2年了.
我的问题是,在您的观点/经验中何时应该使用React Context而不是React Redux,反之亦然?
我正在使用新的React Context API而不是Redux开发一个新的应用程序,之前,Redux当我需要获取用户列表时,我只需调用componentDidMount我的操作,但现在使用React Context,我的操作就在里面我的消费者在我的渲染函数中,这意味着每次调用我的渲染函数时,它都会调用我的动作来获取我的用户列表,这是不好的,因为我会做很多不必要的请求.
那么,我怎么只能调用一次我的动作,比如componentDidMount不是在渲染中调用?
举个例子,看看这段代码:
让我们假设我将所有内容包装Providers在一个组件中,如下所示:
import React from 'react';
import UserProvider from './UserProvider';
import PostProvider from './PostProvider';
export default class Provider extends React.Component {
render(){
return(
<UserProvider>
<PostProvider>
{this.props.children}
</PostProvider>
</UserProvider>
)
}
}
Run Code Online (Sandbox Code Playgroud)
然后我把这个Provider组件包装成我的所有应用程序,如下所示:
import React from 'react';
import Provider from './providers/Provider';
import { Router } from './Router';
export default class App extends React.Component {
render() {
const Component = Router();
return(
<Provider>
<Component />
</Provider>
)
}
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试从Redux Store迁移以使用Apollo Graphql 客户端附带的Apollo 客户端缓存。
将 Apollo Client 与其他数据管理解决方案区分开来的关键特性之一是其规范化缓存。只需设置 Apollo Client,您就可以获得开箱即用的智能缓存,无需额外配置。
使用 Redux,我们必须根据从副作用接收到的响应来编写动作、类型和分派动作,并使用 reducer 设置存储中的数据,这由 Apollo Client 自动完成。
问题:
1) 从 Redux 迁移到 Apollo Client Cache 有什么优势?
2) 在迁移到 Apollo Client Cache 之前,我应该担心什么吗?
将组件添加到入口点时出现问题,此错误立即在此处弹出,该如何解决?我也尝试仅添加Main组件,但是无论如何我都会遇到该错误,在main.jsx中,仅带有渲染方法的类返回“ hello world”
_react.default.createContext is not a function
Run Code Online (Sandbox Code Playgroud)
_react.default.createContext is not a function
Run Code Online (Sandbox Code Playgroud)
Webpack配置
'use strict';
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'eval-source-map',
entry: [
'webpack-hot-middleware/client?reload=true',
path.join(__dirname, 'src/app.jsx')
],
resolve: {
root: [
path.resolve(__dirname, "src"),
],
extensions: ['', '.js', '.jsx', '.css']
},
output: {
path: path.join(__dirname, '/public/'),
filename: '[name].js',
publicPath: '/'
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.tpl.html',
inject: 'body',
filename: 'index.html'
}),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new …Run Code Online (Sandbox Code Playgroud) Next13 一周前发布,我正在尝试将 next12 应用程序迁移到 next13。我想尽可能多地使用服务器端组件,但我似乎无法使用
import { createContext } from 'react';
Run Code Online (Sandbox Code Playgroud)
在任何服务器组件中。
我收到此错误:
Server Error
Error:
You're importing a component that needs createContext. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.
,----
1 | import { createContext } from 'react';
: ^^^^^^^^^^^^^
`----
Maybe one of these should be marked as a client entry with "use client":
Run Code Online (Sandbox Code Playgroud)
这里有其他选择吗?还是我必须诉诸道具钻探来获得服务器端渲染?
我正在创建一个在线购物网站,并尝试为该项目使用 React Typescript,但是当我尝试使用 Contexts 时,当我尝试导出 Provider 值中的状态时,我无法解决此问题
谢谢你的帮助
错误
类型 '{ 产品:IProductItem[] | 不明确的; setProducts: React.Dispatch<React.SetStateAction<IProductItem[] | 未定义>>; }' 不可分配给类型“IProductContext”。对象文字只能指定已知属性,并且类型 '[IProductItem[], Dispatch<SetStateAction<IProductItem[]>>]'.ts(2322) index.d.ts(332, 9) 中不存在 'products':预期类型来自属性“value”,该属性在“IntrinsicAttributes & ProviderProps”类型上声明
上下文代码
import * as React from 'react';
import { useQuery } from "react-query";
type IProductContext = [IProductItem[], React.Dispatch<React.SetStateAction<IProductItem[]>>];
export const ProductContext = React.createContext<IProductContext>([[], () => null]);
const ProductProvider: React.FC<{}> = ({children}: { children?: React.ReactNode }) => {
//fetching products data from a public API
const getProducts = async (): Promise<IProductItem[]> =>
await …Run Code Online (Sandbox Code Playgroud) 在useContextReact 16.8+上使用钩子效果很好。您可以创建一个组件,使用该钩子并利用上下文值而不会出现任何问题。
我不确定的是如何将更改应用于Context Provider值。
1)useContext挂钩是否严格地是一种使用上下文值的方法?
2)是否有推荐的方法,使用React挂钩来更新子组件的值,然后该子组件将使用useContext带有此上下文的挂钩触发任何组件的组件重新渲染?
const ThemeContext = React.createContext({
style: 'light',
visible: true
});
function Content() {
const { style, visible } = React.useContext(ThemeContext);
const handleClick = () => {
// change the context values to
// style: 'dark'
// visible: false
}
return (
<div>
<p>
The theme is <em>{style}</em> and state of visibility is
<em> {visible.toString()}</em>
</p>
<button onClick={handleClick}>Change Theme</button>
</div>
)
};
function App() {
return <Content />
};
const rootElement = …Run Code Online (Sandbox Code Playgroud)我创建了一个 Next.js 应用程序并使用 Firebase 身份验证。我使用 useContext 挂钩来管理应用程序中的用户状态。AuthContext的代码如下:
auth.js
import { createContext, useState, useEffect, useContext } from "react";
import { getAuth, onIdTokenChanged } from "firebase/auth";
const AuthContext = createContext({});
export const AuthProvider = ({children}) => {
const auth = getAuth();
const [user, setUser] = useState(null);
useEffect(() => {
return(onIdTokenChanged(auth, (user) => {
if(user) {
setUser(user);
} else {
setUser(null);
}
}))
},[]);
return(<AuthContext.Provider value={{user}}>{children}</AuthContext.Provider>);
}
export const useAuth = () => useContext(AuthContext);
Run Code Online (Sandbox Code Playgroud)
编辑:我已经在 …
javascript firebase firebase-authentication next.js react-context
MyContext.js
import React from "react";
const MyContext = React.createContext('test');
export default MyContext;
Run Code Online (Sandbox Code Playgroud)
创建了一个上下文单独的js文件,我可以在父文件和子组件中访问它
Parent.js
import MyContext from "./MyContext.js";
import Child from "./Child.js";
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
Message: "Welcome React",
ReturnMessage:""
};
}
render() {
return (
<MyContext.Provider value={{state: this.state}}>
<Child />
</MyContext.Provider>
)
}
}
Run Code Online (Sandbox Code Playgroud)
因此,在Provider选项卡中创建了一个父组件,其中包含Provider上下文和调用子组件
Child.js
import MyContext from "./MyContext.js";
class Child extends Component {
constructor(props) {
super(props);
this.state = {
ReturnMessage:""
};
}
ClearData(context){
this.setState({
ReturnMessage:e.target.value
});
context.state.ReturnMessage = ReturnMessage
} …Run Code Online (Sandbox Code Playgroud) 我正在编写一个使用Firebase进行身份验证的基本CRUD React应用程序.目前我正在尝试为名为Dashboard的组件创建受保护的路由.受保护的路由确保除非用户通过身份验证,否则任何封装的路由(例如仪表板)都不会呈现.如果用户未经过身份验证,则路由器会重定向到目标网页.
我完成此任务的方式是以这篇文章为蓝本的:
我已经模仿了上面文章中的模式,它工作正常.当我合并firebase(特别是firebase身份验证)时,即使用户已登录,我的应用也不会呈现仪表板组件.而只是重定向到登陆页面
我知道问题是什么(我认为),但我不确定如何解决它.
问题是对firebase的调用是异步操作,仪表板在解析对firebase的调用之前尝试加载.
我想知道他们是否可以修改我的代码.
每次用户加载受保护的路由(检查身份验证)时,我都可以对firebase进行api调用,但我更愿意在Context状态下设置身份验证并引用该状态,直到用户登录或注销为止.
我在下面放了相关代码.所有文件都在src目录中
谢谢!
App.js
import React, { Component } from 'react';
import { BrowserRouter, Route, Redirect } from "react-router-dom";
import {Switch} from 'react-router';
import Landing from './PageComponents/Landing';
import {Provider} from './PageComponents/Context';
import Dashboard from './PageComponents/Dashboard';
import ProtectedRoute from './PageComponents/ProtectedRoute';
class App extends Component {
render() {
return (
<div className="App">
<Provider>
<BrowserRouter>
<div>
<Switch>
<Route exact={true} path="/" component={Landing} />
<ProtectedRoute exact path="/dashboard" component={Dashboard} /> …Run Code Online (Sandbox Code Playgroud) javascript firebase reactjs firebase-authentication react-context
react-context ×10
reactjs ×9
javascript ×5
firebase ×2
next.js ×2
react-redux ×2
redux ×2
graphql ×1
react-hooks ×1
typescript ×1