我正在尝试第一次使用React钩子,并且我最终希望替换旧的上下文API。如何实现useContext挂钩来完成全局状态?
我一直在尝试遵循有关Medium,其他Stack溢出文章以及一些随机博客文章的教程。以下是我目前拥有的代码:
APP.JS
{
props: ['value'],
methods: {
mEmit: function(EVT) {
const VAL = EVT.target.value;
var FILTERED = myFilterFunction(VAL);
this.$emit('input', FILTERED);
this.$forceUpdate();
}
}
}
APPCONTEXT.JS
<input type="text" v-bind:value="value" v-on:input="mEmit($event)" />
这两个Form组件基本上是虚拟组件,其中包含最少的JSX。
我不断收到多个“ TypeError:无法读取未定义的属性'page'”错误。这是使用新的useContext钩子的不正确方法吗?
理想情况下,我希望每个表单都有一个链接,当单击该链接时,会将您切换到另一个表单。即,如果您在登录表单中但需要注册,它将更改为注册表单;如果您在注册表单中但已经拥有一个帐户,则会将您切换到登录表单。
答案 0 :(得分:2)
首先,您没有正确使用useContext钩子的Reducer Logic。您必须首先了解,除非在层次结构中有提供者,否则将无法使用上下文。由于AppProvider是在App内部呈现的,因此您将无法在App内部使用上下文。
第二,您不得将组件作为标签存储在reducer中,如果需要,可以存储其引用
所以您的代码最终看起来像
import React from 'react';
import { AppProvider, useAppValue } from './AppContext';
import FormLogin from './FormLogin';
import FormRegister from './FormRegister';
const initialState = {
page: FormLogin
}
const reducer = (state, action) => {
switch (action.type) {
case 'loadLogin':
return {
...state,
page: FormLogin
};
case 'loadRegister':
return {
...state,
page: FormRegister
};
default:
return state;
}
};
const App = () => {
let [{ page: Page }] = useAppValue();
return (
<div className="App">
<Page />
</div>
);
}
export default (props) => (
<AppProvider initialState={initialState} reducer={reducer}>
<App {...props} />
</AppProvider>
)
编辑:确保在页面解构周围添加数组。
答案 1 :(得分:2)
useContext的使用是错误的。您在useContext的层次结构中没有任何Provider。
这是使用我暗示的减速器的示例方法。
在Store.js中,初始化React上下文-
import {createContext} from 'react';
const Context = createContext();
export default Context;
在Reducers.js中,具有通用状态管理系统的逻辑,
import React, {useReducer} from 'react';
import Context from './Store';
const initialState = {
count: 0,
someothervalue: 'hello'
}
function reducer(state, action) {
const {count, ...otherValues} = state;
switch(action.type) {
case 'increment':
return {count: count + 1, ...otherValues};
case 'decrement':
return (count > 0) ? {count: count - 1, ...otherValues} : state;
default:
return state;
}
}
const ReducerProvider = (props) => {
const [state, dispatch] = useReducer(reducer, initialState);
return (<Context.Provider value={{state, dispatch}}>
{props.children}
</Context.Provider>)
}
export default ReducerProvider;
在App.js中,
<ReducerProvider>
..... Your Code .....
</ReducerProvider>
在Component.js中,
import Context from '../Store';
....
....
....
const {state, dispatch} = useContext(Context);
return (... your component logic)