我正在尝试在我的项目中制作一个深色/浅色主题系统,但我的代码遇到一些问题。
这行代码在 javascript 中运行良好:
const [darktheme, setDarkTheme] = useContext(ThemeContext);
Run Code Online (Sandbox Code Playgroud)
但是当我将其写入打字稿时,出现 6 个错误。
我知道其中一些变量需要声明其类型,但我只知道 darkTheme 变量的类型,它是一个布尔值。
声明类型后,2 个错误消失了,但仍然有 4 个错误!
const [darktheme: boolean, setDarkTheme: any] = useContext(ThemeContext);
Run Code Online (Sandbox Code Playgroud)
我使用了任何天黑后的主题,这不是一个好的做法,但我不知道类型
我认为我的项目的主要问题是我试图将 javascript 与 typescript 集成。我不知道这是否正常,但我这样做是因为有些组件用 typescript 编写起来要容易得多,而一些更基本的组件用 javascript 编写更好。
这是我的 app.js 的一部分:
// Context
export const ThemeContext = React.createContext();
function App() {
const [darkTheme, setDarkTheme] = useState(false);
return (
<ThemeContext.Provider value={[darkTheme, setDarkTheme]}>
Run Code Online (Sandbox Code Playgroud)
,当我在这个组件中使用该函数时,它工作得很好:
import React, { useContext } from 'react';
import { ThemeContext } from '../App';
import Button from 'react-bootstrap/Button';
export default …Run Code Online (Sandbox Code Playgroud) 我已经设置了一个 Provider 来为使用useContext. 因此,我试图利用本地存储为用户图像(头像等)保存一些状态。
首先,我试图为用户保留头像,本质上是从 express 保存他们的 ID,然后在我调用 Cloudinary(一种图像托管服务)时使用它。
我想我很接近(因为我获得了头像的默认图像占位符),但我无法设置本地存储。
import React, { useState, useEffect } from 'react';
import dynamic from 'next/dynamic';
var initialState = {
userId: null,
avatar: '/static/uploads/profile-avatars/placeholder.jpg'
};
var UserContext = React.createContext();
function getLocalStorage() {
return Object.keys(initialState).forEach(item => {
dynamic(
() =>
Object.keys(initialState).forEach(
val => (initialState[window.localStorage.getItem(item)] = val)
),
{
ssr: false
}
);
});
}
function setLocalStorage() {
Object.keys(initialState).forEach(item => {
console.log('item setLocalStorage', item);
dynamic(
() =>
window.localStorage.setItem(
item,
Object.values(initialState).forEach(item => item)
),
{ …Run Code Online (Sandbox Code Playgroud) 我创建了一个沙箱来概述主要兴趣点: https://codesandbox.io/s/restless-dawn-nwy0l
请忽略格式,因为这只是我整理的 MWE。
当我在上面的沙箱中运行以下测试时
import React from "react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import Statistics from "../src/components/Block/Statistics";
import { IAction, IState } from "../src/typings/AppTypes";
import { AppReducer } from "../src/reducers/AppReducer";
import { AppContext } from "../src/context/AppContext";
import * as MineUtil from "../src/utils/mine";
import * as ConversionUtil from "../src/utils/conversion";
const state: IState = {
verifiedTrans: [
{
to: "A",
from: "B",
amount: 1.23,
message: "First Transaction",
signature: "AB1.23"
},
{
to: "A",
from: …Run Code Online (Sandbox Code Playgroud)reactjs jestjs react-testing-library use-reducer use-context
我在 React 中创建了以下上下文:
import { useBoolean } from "@chakra-ui/react"
import { createContext, FC } from "react"
type useBooleanReturn = ReturnType<typeof useBoolean>
export const MobileContext = createContext<
[show: useBooleanReturn[0], setShow: useBooleanReturn[1]] | undefined
>(undefined)
// --- PROVIDER
const MobileProvider: FC = ({ children }) => {
const [show, setShow] = useBoolean()
return (
<MobileContext.Provider value={[show, setShow]}>
{children}
</MobileContext.Provider>
)
}
export default MobileProvider
Run Code Online (Sandbox Code Playgroud)
到目前为止一切都很好,但是当我尝试使用这个上下文时,结果发现正在传递的是undefined. 也就是说,下面的代码中value是未定义的:
const value = React.useContext(MobileContext)
Run Code Online (Sandbox Code Playgroud)
不过,我不知道为什么会这样,因为我useBoolean在设置上下文时使用了钩子——即这一行: const [show, setShow] = useBoolean() …
所以我想了解一下,React contexts但我有点困惑。从它的文档:
Context 提供了一种通过组件树传递数据的方法,而无需在每个级别手动向下传递 props。
所以这意味着我可以将应用程序的整个状态设为全局,并且可以从任何子组件更新它,对吧?但是我对如何使用它感到困惑。我有一个小应用程序,可以根据用户的输入向用户显示登录、注册或登录屏幕。我期望以下任何组件都应该能够更改存储在上下文中的全局对象的值,但我不确定如何使用它(提到不确定的函数todos)
// context
const MyAppSettings = React.createContext(
{
userId:null,
enableMarketing:false,
theme:"light"
}
)
Run Code Online (Sandbox Code Playgroud)
//ui components(having access to local state as well as global context
function SettingsUI({onThemeChange,onConsentChange}){
let settings = useContext(MyAppSettings)
return(
<div>
<button onClick={e=>onThemeChange()}>Change Theme to {settings.theme==="light"?"dark":"light"}</button>
<br/>
<button onClick={e=>onConsentChange()}> {settings.enableMarketing?"withdraw consent for marketing emails":"give consent for marketing emails"}</button>
</div>
)
}
function Auth({onAuthClick}){
let settings = useContext(MyAppSettings)
let textColor = settings.theme==="light" ? "black" : "white"
let bg = settings.theme==="light"?"white": "brown" …Run Code Online (Sandbox Code Playgroud) 所以我有一个看起来像这样的组件
const App = () => {
const someContextValue = useSomeContext(); //custom hook that calls useContext
useEffect(() => {
someContextValue()
}, [someContextValue]);
return <div />
}
Run Code Online (Sandbox Code Playgroud)
每当组件重新渲染时,即使 someContextValue 并未真正更改,也会触发 useEffect。
我通过使用 useMemo 解决了这个问题
const someContextValue = useMemo(useSomeContext, [useSomeContext])
现在 someContextValue 在重新渲染时不会改变。但我感觉这不太对劲。这样做的正确方法是什么?
我目前正在尝试弄清楚如何在将应用程序包装在 Context 提供程序中(从 useReducer 获取值)然后通过带有 useEffect 挂钩的子组件进行更新时避免创建无限循环。
CodeSandbox 上有一个问题示例。
显然,如果不在这里重新发布所有代码,就很难谈论这个问题,但关键点是:
根:
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
const value = { state, dispatch };
return (
<Context.Provider value={value}>
...
</Context.Provider>
Run Code Online (Sandbox Code Playgroud)
孩子:
export const Page1: FC = () => {
const { dispatch, state } = useContext(Context);
const { isLoading } = state;
useEffect(() => {
dispatch({
type: "loading",
payload: false
});
}, [dispatch]);
return (...)
Run Code Online (Sandbox Code Playgroud)
我可能遗漏了一些明显的东西,但任何指针都可能会帮助遇到同样问题的其他人。
我设置了一个上下文来分发 Firebase 身份验证对象,如下所示:
export function AuthProvider(props: {children: React.ReactNode}) {
const [user, setUser] = useState<IUser>({uid: ""});
useEffect(() => {
const unsubsribe = firebaseApp.auth().onAuthStateChanged(user => {
if (user) {
setUser(user);
console.log("user: " + user.uid);
}
});
return () => {
unsubsribe();
}
}, [user]);
const authContextValue = {
firebaseApp,
user,
signOut: () => firebaseApp.auth().signOut(),
signIn: (email: string, password: string) => firebaseApp.auth().signInWithEmailAndPassword(email, password),
};
return (
<AuthContext.Provider value={authContextValue}>
{props.children}
</AuthContext.Provider>
)
}
export const useAuth = () => React.useContext(AuthContext);
Run Code Online (Sandbox Code Playgroud)
我尝试像这样使用传递的对象:
const {user} = …Run Code Online (Sandbox Code Playgroud) 而不是传递的props父母和child1(的child2的父) - >到的child2,我想使用createContext和接收与价值useContext。
我试图做的是不正确的,因为我收到了一个错误**'booleanContext' is not defined**。
如何传递createContext状态/值?
App.js
CreatePass 是 SignUp 中的一个组件
const [signUpFirst, setIfSignUp] = useState(true);
const booleanContext = createContext(setIfSignUp);
return (
<booleanContext.Provider value={setIfSignUp}>
<div>
</Switch>
<Route exact path='/signup'>
<SignUp homePage={exitSignUpPage} setUserNumber={setUserID} />
</Route>
<Route exact path='/home'>
<Home userIDNumber={userID} setIfSignUp={setIfSignUp} />
</Route>
<CreatPass />
</Switch>
</div>
</booleanContext.Provider>
);
Run Code Online (Sandbox Code Playgroud)
注册.js
render() {
return (
<div className='signUp-div'>
<Header />
<Router history={history}>
<div className='form-div'>
<Redirect to='/signup/mobile' />
<Switch>
<Route exact path='/signup/mobile' …Run Code Online (Sandbox Code Playgroud) 这里我想创建一个AuthContext来将用户状态共享给其他组件。这里我使用 TypeScript 来设置变量类型。但是当我试图解决这个问题时,我遇到了很多错误。我对这个问题非常困惑。
这是我的AuthContext:
import { createContext, ReactNode, useReducer } from 'react'
import { AuthReducer } from './Reducer';
export interface IState {
isAuthenticated: boolean
user: string | null
token: string | null
}
// interface for action reducer
export interface IAction {
type: 'LOGIN' | 'LOGOUT' | 'REGISTER' | 'FORGOT PASSWORD'
payload?: any
}
interface IAuthProvider {
children: ReactNode
}
const initialState = {
isAuthenticated: false,
user: '',
token: ''
}
export const AuthContext = createContext<IState>(initialState); …Run Code Online (Sandbox Code Playgroud) reactjs ×10
use-context ×10
react-hooks ×5
typescript ×4
use-reducer ×3
javascript ×2
use-state ×2
jestjs ×1
use-effect ×1