无法使用 use reducer 更新状态值
Not able to update state value with use reducer
我正在尝试使用反应上下文和化简器将输入字段值更新为状态,但我无法更新状态。请求帮助。
状态函数:
const handleChangeFor = input => e => {
{
dispatch({
type: UPDATE_FIELD,
payload: { input, e }
});
}
};
减速器:
case UPDATE_FIELD:
return {
...state,
[action.payload.input]: action.payload.value
};
组件:
<InputTextContainer>
<InputSelect
value={addOnCategory}
name="addOnCategory"
onChange={handleChangeFor('addOnCategory')}
>
<InputOption value="" style={{ display: 'none' }}>
Please select
</InputOption>
<InputOption>Add On</InputOption>
<InputOption>Flavours</InputOption>
</InputSelect>
</InputTextContainer>
您的代码有两处错误:
- action.payload.value不存在,是action.payload.e.value
- 您不能在 reducer 中使用该事件,否则您会收到合成事件将被重用的错误,请改用操作中的事件值
- action creator 应该只创建一个对象,在组件中调度它。
const UPDATE_FIELD = 'UPDATE_FIELD';
const reducer = (state, { type, payload }) => {
if (type === UPDATE_FIELD) {
const { input, value } = payload;
return { ...state, [input]: value };
}
};
const handleChangeFor = (input, e) => {
//event will be re used and cause an error
// use value instead of passing event to
// reducer
return {
type: UPDATE_FIELD,
payload: { input, value: e.target.value },
};
};
const PureInput = React.memo(function PureInput({
value,
onChange,
}) {
const r = React.useRef(0);
r.current++;
return (
<label>
pure input rendered: {r.current} times
<input
type="text"
onChange={onChange('pure')}
value={value}
/>
</label>
);
});
const App = () => {
const [state, dispatch] = React.useReducer(reducer, {
name: '',
pure: '',
});
//if you want to optimize you can use useCallback
const handleChange = React.useCallback(
(input) => (e) => dispatch(handleChangeFor(input, e)),
[]
);
return (
<div>
<div>
<input
type="text"
onChange={(e) =>
dispatch(handleChangeFor('name', e))
}
value={state['name']}
/>
</div>
<PureInput
value={state['pure']}
onChange={handleChange}
/>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
我正在尝试使用反应上下文和化简器将输入字段值更新为状态,但我无法更新状态。请求帮助。
状态函数:
const handleChangeFor = input => e => {
{
dispatch({
type: UPDATE_FIELD,
payload: { input, e }
});
}
};
减速器:
case UPDATE_FIELD:
return {
...state,
[action.payload.input]: action.payload.value
};
组件:
<InputTextContainer>
<InputSelect
value={addOnCategory}
name="addOnCategory"
onChange={handleChangeFor('addOnCategory')}
>
<InputOption value="" style={{ display: 'none' }}>
Please select
</InputOption>
<InputOption>Add On</InputOption>
<InputOption>Flavours</InputOption>
</InputSelect>
</InputTextContainer>
您的代码有两处错误:
- action.payload.value不存在,是action.payload.e.value
- 您不能在 reducer 中使用该事件,否则您会收到合成事件将被重用的错误,请改用操作中的事件值
- action creator 应该只创建一个对象,在组件中调度它。
const UPDATE_FIELD = 'UPDATE_FIELD';
const reducer = (state, { type, payload }) => {
if (type === UPDATE_FIELD) {
const { input, value } = payload;
return { ...state, [input]: value };
}
};
const handleChangeFor = (input, e) => {
//event will be re used and cause an error
// use value instead of passing event to
// reducer
return {
type: UPDATE_FIELD,
payload: { input, value: e.target.value },
};
};
const PureInput = React.memo(function PureInput({
value,
onChange,
}) {
const r = React.useRef(0);
r.current++;
return (
<label>
pure input rendered: {r.current} times
<input
type="text"
onChange={onChange('pure')}
value={value}
/>
</label>
);
});
const App = () => {
const [state, dispatch] = React.useReducer(reducer, {
name: '',
pure: '',
});
//if you want to optimize you can use useCallback
const handleChange = React.useCallback(
(input) => (e) => dispatch(handleChangeFor(input, e)),
[]
);
return (
<div>
<div>
<input
type="text"
onChange={(e) =>
dispatch(handleChangeFor('name', e))
}
value={state['name']}
/>
</div>
<PureInput
value={state['pure']}
onChange={handleChange}
/>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>