在函数组件中从 Redux Store 接收新值时 useState 不起作用
useState not working when receiving new values from Redux Store in Function Component
关于这个 StackBlitz (you can play with) 我有以下代码:
App.js
import { Field, Form, Formik } from 'formik';
import React, { useState } from 'react';
import { Provider, useDispatch, useSelector } from 'react-redux';
import store, { userActions } from './store';
const Suggestion = () => {
const dispatch = useDispatch();
const { color } = useSelector(state => state.user);
return (color === 'Yellow') ? (
<div>
We recommend you to change to Green.<br />
<a href="#" onClick={() => { dispatch(userActions.save({ color: 'Green' })); }}>Change Now!</a>
</div>
) : null;
};
const MyComp = () => {
const dispatch = useDispatch();
const userData = useSelector(state => state.user);
const initialValues = {
color: 'Green',
};
const [ formValues, setFormValues ] = useState((userData.length > 0) ? userData : initialValues);
console.log(JSON.stringify({ userData, formValues }));
const onSubmit = (values) => {
dispatch(userActions.save(values));
};
return (
<Formik
initialValues={formValues}
onSubmit={onSubmit}
enableReinitialize
>
{formik => {
const handleChange = (partialUserData) => {
setFormValues({
...formValues,
...partialUserData
});
formik.submitForm();
};
return (
<Form>
<h2>What Color do you use?</h2>
<Field id="color" as="select" value={formValues.color} onChange={(e) => { handleChange({ color: e.target.value }); }}>
<option value=''>Select...</option>
<option value='Green'>Green</option>
<option value='Yellow'>Yellow</option>
</Field>
<Suggestion />
</Form>
);
}}
</Formik>
);
};
export default () => {
return (
<Provider store={store}>
<MyComp />
</Provider>
);
};
store.js
import { configureStore, createSlice } from '@reduxjs/toolkit';
const userSlice = createSlice({
name: 'user',
initialState: {},
reducers: {
save(state, action) {
for (const key in action.payload) {
state[key] = action.payload[key];
}
},
},
});
const store = configureStore({
reducer: {
user: userSlice.reducer,
},
devTools: true,
});
export const userActions = userSlice.actions;
export default store;
预期功能
- “绿色”select默认设置
- 你select“黄色”,下面出现一条建议(你在控制台上得到:“黄色”)
- 您 select“绿色”并且建议消失(您在控制台上得到:“绿色”)
- 执行上面的第 2 步
- 您点击link:“立即更改!”
- 选项“绿色”得到 select 编辑并且建议消失(您在控制台上得到:“绿色”)
我的问题是:
第 6 步并不完全有效,因为即使建议消失了,这很好,选项:“绿色”没有得到 selected 并且在控制台上我仍然得到:“黄色”。
由于某种原因,该行...
const [ formValues, setFormValues ] = useState(...);
... 未保存变量存储中的值:formValues
因为 userData
具有预期值,如下图所示...
知道如何进行这项工作吗?
谢谢!
我不知道获取新储值的正确方法是什么。但我可以建议的是创建一个 useEffect 挂钩来设置每次 userData
更改时运行的新表单值。
useEffect(() => {
setFormValues(userData)
}, [userData])
不,那是错误的React.useState(defaultValue)
它只是用于组件渲染的 React.useState
的默认值,它不会监听新的变化。
你需要使用 React.useEffect()
钩子,如果你将依赖项数组留空,那么 useEffect
将只在组件渲染时调用一次,但如果你将依赖项作为你的 redux 数据传递然后每次你的依赖数据改变时 useEffect
将被调用。
最后你的代码会像这样
const dispatch = useDispatch();
const userData = useSelector(state => state.user);
const initialValues = {
color: 'Green',
};
const [ formValues, setFormValues ] = useState(initialValues);
React.useEffect(()=>{
setFormValues((userData.length > 0) ? userData : initialValues);
// cleanup function which will be invoked on component unmount
return ()=> {
setFormValues(userData)
}
},[useData]);
console.log(JSON.stringify({ userData, formValues }));
const onSubmit = (values) => {
dispatch(userActions.save(values));
};
关于这个 StackBlitz (you can play with) 我有以下代码:
App.js
import { Field, Form, Formik } from 'formik';
import React, { useState } from 'react';
import { Provider, useDispatch, useSelector } from 'react-redux';
import store, { userActions } from './store';
const Suggestion = () => {
const dispatch = useDispatch();
const { color } = useSelector(state => state.user);
return (color === 'Yellow') ? (
<div>
We recommend you to change to Green.<br />
<a href="#" onClick={() => { dispatch(userActions.save({ color: 'Green' })); }}>Change Now!</a>
</div>
) : null;
};
const MyComp = () => {
const dispatch = useDispatch();
const userData = useSelector(state => state.user);
const initialValues = {
color: 'Green',
};
const [ formValues, setFormValues ] = useState((userData.length > 0) ? userData : initialValues);
console.log(JSON.stringify({ userData, formValues }));
const onSubmit = (values) => {
dispatch(userActions.save(values));
};
return (
<Formik
initialValues={formValues}
onSubmit={onSubmit}
enableReinitialize
>
{formik => {
const handleChange = (partialUserData) => {
setFormValues({
...formValues,
...partialUserData
});
formik.submitForm();
};
return (
<Form>
<h2>What Color do you use?</h2>
<Field id="color" as="select" value={formValues.color} onChange={(e) => { handleChange({ color: e.target.value }); }}>
<option value=''>Select...</option>
<option value='Green'>Green</option>
<option value='Yellow'>Yellow</option>
</Field>
<Suggestion />
</Form>
);
}}
</Formik>
);
};
export default () => {
return (
<Provider store={store}>
<MyComp />
</Provider>
);
};
store.js
import { configureStore, createSlice } from '@reduxjs/toolkit';
const userSlice = createSlice({
name: 'user',
initialState: {},
reducers: {
save(state, action) {
for (const key in action.payload) {
state[key] = action.payload[key];
}
},
},
});
const store = configureStore({
reducer: {
user: userSlice.reducer,
},
devTools: true,
});
export const userActions = userSlice.actions;
export default store;
预期功能
- “绿色”select默认设置
- 你select“黄色”,下面出现一条建议(你在控制台上得到:“黄色”)
- 您 select“绿色”并且建议消失(您在控制台上得到:“绿色”)
- 执行上面的第 2 步
- 您点击link:“立即更改!”
- 选项“绿色”得到 select 编辑并且建议消失(您在控制台上得到:“绿色”)
我的问题是:
第 6 步并不完全有效,因为即使建议消失了,这很好,选项:“绿色”没有得到 selected 并且在控制台上我仍然得到:“黄色”。
由于某种原因,该行...
const [ formValues, setFormValues ] = useState(...);
... 未保存变量存储中的值:formValues
因为 userData
具有预期值,如下图所示...
知道如何进行这项工作吗?
谢谢!
我不知道获取新储值的正确方法是什么。但我可以建议的是创建一个 useEffect 挂钩来设置每次 userData
更改时运行的新表单值。
useEffect(() => {
setFormValues(userData)
}, [userData])
不,那是错误的React.useState(defaultValue)
它只是用于组件渲染的 React.useState
的默认值,它不会监听新的变化。
你需要使用 React.useEffect()
钩子,如果你将依赖项数组留空,那么 useEffect
将只在组件渲染时调用一次,但如果你将依赖项作为你的 redux 数据传递然后每次你的依赖数据改变时 useEffect
将被调用。
最后你的代码会像这样
const dispatch = useDispatch();
const userData = useSelector(state => state.user);
const initialValues = {
color: 'Green',
};
const [ formValues, setFormValues ] = useState(initialValues);
React.useEffect(()=>{
setFormValues((userData.length > 0) ? userData : initialValues);
// cleanup function which will be invoked on component unmount
return ()=> {
setFormValues(userData)
}
},[useData]);
console.log(JSON.stringify({ userData, formValues }));
const onSubmit = (values) => {
dispatch(userActions.save(values));
};