React form custom hook?

I have no idea why this isn’t working, but here is my custom hook:

import { useState } from 'react';

const useInputState = (initialState: any) => {
  const [inputs, setInputs] = useState(initialState);
  const handleInputChange = (event: any) => {
    if (event) {
      event.persist();
      setInputs((inputs: any) => ({
        ...inputs,
        [event.target.name]: event.target.value,
      }));
    }
  };
  return {
    inputs,
    handleInputChange,
  };
};

export default useInputState;

Then here is my form:

import React, { useState } from 'react';
import useInputState from '../../hooks/useInputState';
import { FormGroup, TextField, Button } from '@material-ui/core';
import { validateForm, submitForm } from '../../helperFunctions';
import FormSelect from './FormSelect';

import { formStyles } from './FormStyles/FormStyles';

const EventSignUpForm: React.FC = () => {
  const { inputs, handleInputChange } = useInputState({
    firstName: '',
    lastName: '',
    email: '',
    company: '',
    role: '',
  });

  const handleSubmit = (e: any) => {
    e.preventDefault();

  };

  return (
    <form className="EventSignUpForm" onSubmit={handleSubmit}>
      <FormGroup>
        <div>
          <TextField
            inputProps={{ style: formStyles.textField }}
            label="First Name"
            variant="filled"
            value={inputs.firstName}
            onChange={handleInputChange}
            required
          />
          <TextField
            inputProps={{ style: formStyles.textField }}
            label="Last Name"
            variant="filled"
            value={inputs.lastName}
            onChange={handleInputChange}
            required
          />
        </div>

        <TextField
          inputProps={{ style: formStyles.textField }}
          label="E-mail"
          variant="filled"
          type="email"
          value={inputs.email}
          onChange={handleInputChange}
          required
        />
        <div className="formTestDiv">
          <TextField
            inputProps={{ style: formStyles.textField }}
            label="Company"
            variant="filled"
            value={inputs.company}
            onChange={handleInputChange}
            required
          />
          <FormSelect
            role={inputs.role}
            setRole={handleInputChange}
            styles={formStyles}
          />
        </div>
      </FormGroup>

      <Button style={formStyles.button} type="submit" value="Submit">
        Submit
      </Button>
    </form>
  );
};

export default EventSignUpForm;

Can anyone see what is going on?

I’m not sure this is valid syntax and valid use of useState setter function (though I might be incorrect). Normally I would expect it to be:

const { name, value } = event.target;
const current = {};
current[name] = value;
setInputs({ ...inputs, ...current });

*UPDATED WITH CLEANER CODE

Or assuming TS:

const { name, value } = event.target;
setInputs({ ...inputs, [name]: value });

I have a working version actually of this from a while back:

import { useState } from "react"

export default initialVal => {
  const [value, setValue] = useState(initialVal)
  const handleChange = e => {
    console.log(e)
    setValue(e.target.value)
  }
  
  const reset = () => {
    setValue("")
  }

  return [value, handleChange, reset]
}

Curious to see if I can use it in this project and then going to try your solution and try to compare them.

You see, here you’re not passing function as in your code above, but state

Somehow, my code still doesn’t work lol

Trying to keep the state in one object with the spread…

Would’ve thought this could work but my IDE is screaming:

import { useState } from 'react';

export default (initialVal: any) => {
  const [value, setValue] = useState(initialVal);
  const handleChange = (e: any) => {
    e.persist();

    setValue((value) => {
      ...value,
      [e.target.name]: e.target.value
    });
  };

  const reset = () => {
    setValue('');
  };

  return [value, handleChange, reset];
};

You don’t have a name attribute on the elements so event.target.name is an empty string.

1 Like

UGH! The day is too long. Thank you.

No problem. You might want to get in the habit of just console logging the f out of everything. If you expect a value, check it.

Side node. I’m not really a TS guy but if you just any type everything and don’t set up interfaces, return types, expected types/values, etc. I think you lose a lot of the actual benefit of using TS. I think VS Code has pretty good integration, like Ctrl + Space completion and on hover indications, etc. But like I said I don’t really use TS much.

Definitely thank you so much. As far as I have understood it, if you are expecting an object you put any, but I need to dig in further.