我试图通过使用一个简单的服务来抽象我的 API 调用,该服务提供了一个非常简单的方法,这只是一个 HTTP 调用。我将此实现存储在 React Context 中,并在 my 中使用其提供程序_app.js,以便该 API 全局可用,但我在实际使用页面中的上下文时遇到问题。
页面/_app.js
import React from 'react'
import App, { Container } from 'next/app'
import ApiProvider from '../Providers/ApiProvider';
import getConfig from 'next/config'
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig()
export default class Webshop extends App
{
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
render () {
const { Component, pageProps …Run Code Online (Sandbox Code Playgroud) 我有一个组件(EmailBuilder),它使用react context api来渲染一些东西,我想将其渲染为html,我尝试了这个:
import * as React from 'react'
import { EmailBuilder } from './EmailBuilder';
import ReactDOMServer from 'react-dom/server';
export const EmailBuilderPage = (props: any) => {
const element = <EmailBuilder />
return <>
{element}
<br />
<h1>HTML</h1>
{ReactDOMServer.renderToString(element)}
</>
}
Run Code Online (Sandbox Code Playgroud)
虽然渲染了元素的根,但它无法渲染上下文 api 对元素的任何更改。
这可能吗?
我见过的React上下文的每个例子都是这样的:
theme-context.js
// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {},
});
Run Code Online (Sandbox Code Playgroud)
您的文件包含上下文的实例。然后使用将其传递到组件中useContext(ThemeContext)。
我的问题是,如果你这样做并且它始终是单例,那么为什么不直接从单例导入上下文中的内容呢?基本上我想知道是否有一次您创建了多个上下文实例,例如为了测试,您可能会在每次测试时创建一个新实例,类似的事情。
我是 React Context 的新手。我需要在 React 上下文中调用 API,以便在整个 React 应用程序中使用其数据。此外,还需要对 React 应用程序的各个组件上的某些 CRUD 操作调用相同的 API。
现在我将 API 数据存储在 redux 中,但我不想存储它。
这是我尝试过的..
context.js 文件
import React, { useState, createContext,useEffect } from 'react';
import {getData} from './actionMethods';
const NewContext = createContext();
function newContextProvider(props) {
useEffect(async () => {
const {dataValue} = await getData()
console.log("Data " , dataValue)
}, [])
return (
<NewContext.Provider
value={{
state: {
},
actions: {
}
}}
>
{props.children}
</NewContext.Provider>
);
}
const newContextConsumer = newContext.Consumer;
export { newContextProvider, newContextConsumer, …Run Code Online (Sandbox Code Playgroud)我有一个StatusContext这样命名的上下文:
export const statusCtxInit = {
open: false,
toggleOpen() {
this.open = !this.open;
}
};
const StatusContext = React.createContext(statusCtxInit);
export default StatusContext
Run Code Online (Sandbox Code Playgroud)
整个应用程序都与提供者一起包装:
// ...
<StatusContext.Provider value={statusCtxInit}>
// ...
Run Code Online (Sandbox Code Playgroud)
useContext为了使用我在 FC 中使用的上下文的值,当我获得该值时它就会起作用。
function MyComp() {
const status = useContext(StatusContext);
return (
<div>
{status.open
? `It's Open`
: `It's Closed`}
<button onClick={() => status.toggleOpen()}>
Toggle
</button>
</div>
)
}
export default MyComp
Run Code Online (Sandbox Code Playgroud)
另一方面,我也想通过调用来更改上下文toggleOpen,但是它不能按我想要的方式工作。实际上该值发生变化但不影响MyComp.
我做错了什么?我该怎么办?
我有一个使用类实例作为上下文值的上下文。在我更新了类实例之后。这种变化不会反映在消费者身上。消费者仍然可以获得旧类别的价值。有人可以指出我如何实现这一目标的方向吗?
// Service class
class Service {
name = "oldName"
function changeName(newName){
this.name = newName;
}
}
//Context provider
function App() {
const service = new Service();
return (
<ServiceContext.Provider value={service}>
<Home />
</ServiceContext.Provider>
);
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试在一个组件中更改此服务的名称属性。
import React, { useContext } from "react";
const SomeComponent = () => {
const service = useContext(ServiceContext);
const onClick = () => {
service.changeName('newName')
console.log(service.name) //here the name has updated
}
return <button onClick={onClick}>Change</h1>;
};
Run Code Online (Sandbox Code Playgroud)
并尝试从组件中获取更新后的值。
import React, { useContext } from "react"; …Run Code Online (Sandbox Code Playgroud) 我想在下面的代码中使用正确的 TS 类型,而不是任何类型。我是反应 TS 的新手,请帮助...
如何为以下上下文 API 代码设置 useReducer useContext 的打字稿类型:
import React, {createContext, Dispatch} from 'react';
import {firebaseUser} from '../@types/User';
interface Actions {
SET_IMAGENAME: string;
SET_USER: string;
}
export const Actions: Actions = {
SET_IMAGENAME: 'SET_IMAGENAME',
SET_USER: 'SET_USER',
};
function action(type: string) {
return {type};
}
function actionPayload(type: string, payload: any) { //here
return {type, payload};
}
export const Dispatches = {
setImageName: action,
setUser: actionPayload,
};
interface State {
imgName: string;
user: firebaseUser;
}
const initialState = { …Run Code Online (Sandbox Code Playgroud) typescript reactjs react-context react-typescript use-reducer
我需要获取在特定事件上调用的函数内而不是渲染器内的上下文的当前值。
logCurrentTheme.js
import React, { useContext } from 'react';
import {ThemeContext} from "./ThemeContext";
// ThemeContext is a context created by React.createContext()
function logCurrentTheme() {
const context = useContext(ThemeContext);
console.log(context.themeColor)
}
export {logCurrentTheme};
Run Code Online (Sandbox Code Playgroud)
在我的其他一些组件中
//...
import {logCurrentTheme} from "./logCurrentTheme.js";
//...
const someComponent () => {
return(
<Button onClick={logCurrentTheme} title="Log Current Theme"/>
);
}
Run Code Online (Sandbox Code Playgroud)
上面的例子编译成功,但是一旦单击按钮就会抛出错误:
无效的挂钩调用。钩子只能在函数组件体内调用
我知道这是一个“函数”而不是“函数组件”。但我还能怎样做呢?
编辑:
LogContextButton.js
import React from "react";
import { useContextHelper } from "./ContextHelper";
export const LogContextButton = props => {
var { logCurrentContextValue …Run Code Online (Sandbox Code Playgroud) 我最初关注这个项目是为了将 Firebase 添加到 Gatsby React 应用程序中。它涉及创建 Firebase 上下文,使用提供者包装根布局,然后使用 withFirebase HOC 根据需要使用 Firebase 使用者包装组件。当我最初这样做时,它工作得很好,但我想将代码移动到一个可以在我的应用程序中重用的包中。这是 HOC
export const withFirebase = (Component) => (props) => (
<FirebaseContext.Consumer>
{(firebase) => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
Run Code Online (Sandbox Code Playgroud)
每个页面都以一个呈现以下内容的布局组件开始:
<FirebaseContext.Provider value={this.state.firebase}>
<AppWithAuthentication>
{this.props.children}
</AppWithAuthentication>
</FirebaseContext.Provider>
Run Code Online (Sandbox Code Playgroud)
AppWithAuthentication它本身使用withFirebaseHOC,因为它需要 Firebase 来获取 AuthUser(然后将其存储在上下文中并通过提供者传递),并且它能够很好地做到这一点。
上述所有情况都发生在包代码本身中,但是当我将包导入到其他 React 项目中时,尝试使用 usewithFirebase停止工作,因为用它包装的任何组件都不会收到更新的上下文。我通过检查 React Dev 工具中的组件树来确认这一点,Firebase Provider 获取更新的非空值,内部的使用者AppWithAuthentication也获取它。但我的实际应用程序内的消费者不会更新(并且我在同一库中创建的 AuthUser 上下文也有同样的问题)。
我什至认为,也许父级正在使用更新后的消费者进行渲染,但子级没有重新渲染,但在计算渲染并记录它们之后,很明显,我的应用程序中的组件渲染的次数比AppWithAuthentication. 为了让它更清楚一点,这是我的组件树(从页面根目录的布局组件开始):

这是AppWithAuthentication消费者显示的值:

我完全被困在这里,希望得到任何见解。
编辑:经过更多测试后,我发现了更多信息,但我仍然陷入困境。看起来,当重新加载我的页面时,该Layout组件呈现 …
在 React 中,有一种简单的方法可以在多层组件中共享“信息”。这是通过使用上下文
import {UserCtx} from "./stores/UserCtx";
<UserCtx.Provider value={new user(info)}>
<SomeComponent />
</UserCtx.Provider/>
Run Code Online (Sandbox Code Playgroud)
然后在某个组件中:
import {UserCtx} from "./stores/UserCtx";
function SomeComponent() {
const userData = React.useContext(UserCtx);
return <div>JSON.stringify(userData)</div>
}
Run Code Online (Sandbox Code Playgroud)
然而,这要求上下文对象定义对于所有对象都是可见的。因此,当创建组件库时,它不能真正被使用吗?
假设上面的“示例”SomeComponent是一个库组件,我如何将主应用程序的上下文共享给该组件?通过添加属性来共享似乎有些牵强,在这一点上我不妨直接提供用户(或上下文存储的任何内容)?
react-context ×10
reactjs ×10
javascript ×3
next.js ×1
react-dom ×1
react-hooks ×1
typescript ×1
use-reducer ×1
webpack ×1