1

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;
        });
    }
clattenburg cake
  • 1,096
  • 3
  • 19
  • 40
  • 2
    The `required` attribute only works with default form actions. You'll need to do your own validation in the handler. Also, if you want the form's `onSubmit` to not reload the page then you need to invoke `preventDefault()` on the `onSubmit` event object. You should also explicitly define the button `type` attribute as well since buttons by default are `type="submit"`. – Drew Reese Nov 23 '20 at 03:44

2 Answers2

2

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>
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
1

you can do something like this

    function onAddButtonClick(e) {
        e.preventDefault();

     if(playerName.trim()===''){ //you can make more validations here
       return;
     } 
    //down here use the rest of logic
   }