cra*_*rog 5 javascript reactjs redux formik
<Field as="select">我的Formik有问题。效果onChange不佳 - 无论我选择什么选项,当我提交表单时,它都会以空字符串形式发送player1and 。player2
例如输出console.log(values):
{ id: '10', player1: '', player2: '', winner: '1', date: '2021-12-16' }
Run Code Online (Sandbox Code Playgroud)
当我删除onChange它时效果很好,但我需要 onChange 和 selectedPlayer 状态,因为如果我选择 a player1,我不希望他在第二个选项中可见,反之亦然。为什么当更改时value,我的属性没有改变?看起来它获取的初始值是空字符串。FieldselectedPlayerselectedPlayer
import { Field, Form, Formik } from 'formik';
import { connect } from 'react-redux';
import {addMatchAction} from "../../ducks/matches/operations";
import {getAllPlayers} from "../../ducks/players/selectors";
import {useState} from "react";
const MatchesForm = ({ addMatchAction,error,players }, props) => {
const handleSubmit = (values) => {
console.log(values)
addMatchAction(values);
}
const [selectedPlayer1,setSelectedPlayer1] = useState('')
const [selectedPlayer2,setSelectedPlayer2] = useState('')
return (
<div>
<h3>Add match</h3>
<Formik
initialValues={{
id: '',
player1: '',
player2: '',
winner: '',
date: ''
}}
onSubmit={(values) => handleSubmit(values)}
enableReinitialize={true}>
<Form>
<label htmlFor="id">Id: </label>
<Field name="id" />
<label htmlFor="player1">Player 1: </label>
<Field as="select" name="player1" onChange={(e) => setSelectedPlayer1(e.target.value)} value={selectedPlayer1}>
<option disabled value="">(Select a player 1)</option>
{players && players.map(player => {
if (player.id !== selectedPlayer2) {
return (
<option value={player.id}>{player.firstName} {player.lastName}</option>
)
}
}) }
</Field>
<p>
<label htmlFor="player2">Player 2: </label>
<Field as="select" name="player2" onChange={(e) => setSelectedPlayer2(e.target.value)} value={selectedPlayer2}>
<option disabled value="">(Select a player 2)</option>
{players && players.map(player => {
if (player.id !== selectedPlayer1) {
return (
<option value={player.id}>{player.firstName} {player.lastName}</option>
)
}
}) }
</Field>
</p>
<label htmlFor="winner">Winner: </label>
<Field as="select" name="winner">
<option disabled value="">Pick a winner</option>
{players && players.map(player => {
if (player.id === selectedPlayer1 || player.id === selectedPlayer2 ) {
return (
<option value={player.id}>{player.firstName} {player.lastName}</option>
)
}
})}
</Field>
<label htmlFor="date">Date: </label>
<Field name="date" type="date" />
<button type="submit">
Zatwierdz
</button>
</Form>
</Formik>
<p>{error && (<span>{error.name} {error.response.message}</span>)}</p>
</div>
)
}
const mapStateToProps = (state) => {
return {
error: state.error.error,
players: getAllPlayers(state)
}
}
const mapDispatchToProps = ({
addMatchAction
});
export default connect(mapStateToProps, mapDispatchToProps)(MatchesForm);
Run Code Online (Sandbox Code Playgroud)
小智 3
我认为您不了解 Formik 和这个 Field 组件是如何工作的。Formik 使用其自己的内部状态来处理所有 Form 状态,因此您应该在这种情况下使用它并避免使用 useState。您可以执行以下操作:
这是代码。我还重构了 array.map 函数,因为对于这些场景使用数组过滤器更正确(map 应始终返回数组中相同数量的元素)
const MatchesForm = ({ addMatchAction,error,players }, props) => {
const handleSubmit = (values) => {
console.log('submit', values)
addMatchAction(values);
}
return (
<div>
<h3>Add match</h3>
<Formik
initialValues={{
id: '',
player1: '',
player2: '',
winner: '',
date: ''
}}
onSubmit={(values) => handleSubmit(values)}
enableReinitialize={true}>
{props => {
// Try a console.log here to see props and props.values and you will see them updating on every change
// console.log('Values', props.values);
return (
<Form>
<label htmlFor="id">Id: </label>
<Field name="id" />
<label htmlFor="player1">Player 1: </label>
<Field as="select" name="player1">
<option disabled value="">(Select a player 1)</option>
{players && players.filter(player => player.id !== props.values.player2).map(player => (
<option value={player.id}>{player.firstName} {player.lastName}</option>
))}
</Field>
<p>
<label htmlFor="player2">Player 2: </label>
<Field as="select" name="player2" >
<option disabled value="">(Select a player 2)</option>
{players && players.filter(player => player.id !== props.values.player1).map(player => (
<option value={player.id}>{player.firstName} {player.lastName}</option>
))}
</Field>
</p>
<label htmlFor="winner">Winner: </label>
<Field as="select" name="winner">
<option disabled value="">Pick a winner</option>
{players && players.filter(player => player.id === props.values.player1 || player.id === props.values.player2).map(player => (
<option value={player.id}>{player.firstName} {player.lastName}</option>
))}
</Field>
<label htmlFor="date">Date: </label>
<Field name="date" type="date" />
<button type="submit">
Zatwierdz
</button>
</Form>
)
}}
</Formik>
<p>{error && (<span>{error.name} {error.response.message}</span>)}</p>
</div>
)
}
Run Code Online (Sandbox Code Playgroud)