I have a component in React that has required
in its fields. The idea is onClick
will trigger a separate function that adds a soccer player to two different stores (similar to a TODO app). However, it appears that the validation does not work -name
for example is a required string
, but the form seems to add a player even if the string is empty. The same goes for the two number
inputs.
I don't want to use onSubmit
because this seems to refresh the page every time, which causes me to lose data.
I'm using the react-modal
library for my forms. To start with here's a function that opens the modal:
function renderAddButton() {
return (
<Row
horizontal='center'
vertical='center'
onClick={openModal}
>
Add Player
</Row>
);
}
Here's the modal and its hooks:
const [playerName, setPlayerName] = useState('');
const [totalGoals, setTotalGoals] = useState(0);
const [goalPercentage, setGoalPercentage] = useState(0);
function openModal() {
setIsOpen(true);
}
function closeModal() {
setIsOpen(false);
}
<Modal
isOpen={modalIsOpen}
onRequestClose={closeModal}
style={modalStyles}
contentLabel='Player Form Modal'
>
<h3>Create Player</h3>
<form>
<label>Name</label>
<input
type='string'
id='playerNameId'
name='playerName'
defaultValue=''
onChange={(e) => setPlayerName(e.target.value)}
required
/>
<label>Total Goals</label>
<input
type='number'
id='totalGoalsId'
name='totalGoals'
defaultValue='0'
min='0'
onChange={(e) => setTotalGoals(e.target.value)}
required
/>
<label>Goal Percentage</label>
<input
type='number'
id='goalPercentageId'
name='playerGoalPercentage'
defaultValue='0'
min='0'
step ='0.01'
max='1'
onChange={(e) => setGoalPercentage(e.target.value)}
required
/>
<button onClick={(e) => onAddButtonClick(e)}>Submit</button>
</form>
<button onClick={closeModal}>close</button>
</Modal>
And now when this function is triggered, the validations don't seem to work. Empty playerId
and totalGoals
and goalPercentage
seem to go through fine. How do I validate the inputs and stop this function from running if the inputs are empty?
function onAddButtonClick(e) {
e.preventDefault();
setItems((prev) => {
const newItems = [...prev];
const uuid= uuidv4();
newItems.push({
name: playerName,
playerId:uuid,
teamId: currentTeam[0].teamId,
totalGoals: totalGoals,
goalPercentage: goalPercentage
});
playersStore.push({
name: playerName,
playerId:uuid,
teamId: currentTeam[0].teamId,
totalGoals: totalGoals,
goalPercentage: goalPercentage
});
return newItems;
});
}
The required
attribute only works with default form actions. You'll need to do your own validation in the handler. You should also explicitly define the button type
attribute as well since buttons by default are type="submit"
.
Create a validation function and pass your state values to it. Return true if input is valid, false otherwise.
const validateInput = ({ goalPercentage, playerName, totalGoals }) => {
if (!playerName.trim()) {
return false;
}
// other validations
return true;
};
Check the input in onAddButtonClick
and only update state if input is valid.
function onAddButtonClick(e) {
e.preventDefault();
const validInput = validateInput({ goalPercentage, playerName, totalGoals });
if (!validInput) {
return null;
}
setItems((prev) => {
const newItems = [...prev];
const uuid= uuidv4();
newItems.push({
name: playerName,
playerId: uuid,
teamId: currentTeam[0].teamId,
totalGoals: totalGoals,
goalPercentage: goalPercentage
});
playersStore.push({
name: playerName,
playerId: uuid,
teamId: currentTeam[0].teamId,
totalGoals: totalGoals,
goalPercentage: goalPercentage
});
return newItems;
});
}
Update the button to have an explicit type.
<button
type="button"
onClick={onAddButtonClick}
>
Submit
</button>