0

I've got a split date component (with 3 seperate inputs for day, month & year) - the component looked like so:

const DateInput = ({ name, onValueChange, dateInputValue }: Props) => {
  const [day, setDay] = useState("");
  const [month, setMonth] = useState("");
  const [year, setYear] = useState("");

  const storedDateValue = useRef();

  console.log("Base date value: " + dateInputValue);

  const changeDate = useCallback(
    (birthday) => {
      onValueChange(birthday);
    },
    [onValueChange]
  );

  useEffect(() => {
    if (day !== "" && month !== "" && year !== "") {
      const dateValue = `${day}-${month}-${year}`;

      if (storedDateValue.current !== dateValue) {
        storedDateValue.current = dateValue;

        changeDate(dateValue);
      }
    }
  }, [day, month, year, changeDate]);

  return (
    <StyledInputGroup>
      <label htmlFor={`${name}_day`}>
        <span>Day</span>
        <StyledInput
          type="text"
          maxLength="2"
          name={`${name}_day`}
          id={`${name}_day`}
          label="Day"
          value={day}
          onChange={(e) => setDay(e.target.value)}
        />
      </label>
      <label htmlFor={`${name}_month`}>
        <span>Month</span>
        <StyledInput
          type="text"
          maxLength="2"
          name={`${name}_month`}
          id={`${name}_month`}
          label="Month"
          value={month}
          onChange={(e) => setMonth(e.target.value)}
        />
      </label>
      <label htmlFor={`${name}_year`}>
        <span>Year</span>
        <StyledInput
          type="text"
          maxLength="4"
          name={`${name}_year`}
          id={`${name}_year`}
          value={year}
          onChange={(e) => setYear(e.target.value)}
        />
      </label>
    </StyledInputGroup>
  );
};

But I made the following change so that if an initial value was present, then the date inputs would be pre-populated by updating the useState hook like so:

  const [intialDay, initialMonth, initialYear] = dateInputValue.split("-");
  const [day, setDay] = useState(intialDay);
  const [month, setMonth] = useState(initialMonth);
  const [year, setYear] = useState(initialYear);

This meant that we set the day/month/year to the initial value as opposed to an empty string. However, when the fields are blank, and values added, they don't appear to be picked up and results in validation still firing an empty input. When I log to the console it appears that the setState hook isn't working unless working off an intialDay/month/year value. Can anyone spot where I'm going wrong?

cts
  • 908
  • 1
  • 9
  • 30
  • I assume the validation you're talking about is in `StyledInput`? – Sergiu Paraschiv Aug 23 '21 at 14:20
  • well yeah - the onChange function in each of the `StyledInput` is where I assume the issue could be, as it doesn't seem to know how to update the state from `undefined` to the new string value – cts Aug 23 '21 at 14:22
  • Could you update this fiddle https://jsfiddle.net/wams130g/ until you can reproduce the issue? That one works, so it must mean either I don't understand the problem or the problem is somewhere in code you've not added to the question. – Sergiu Paraschiv Aug 23 '21 at 14:24
  • The fiddle won't replicate the issue as the reason for the re-factor (using initialDay etc) was so that when `dateInputValue` had a value - I could pre-populate the input. The `dateInputValue` is passed down from a parent component hence why I used `const [initialDay, initialMonth, initialYear] = dateInputValue.split("-");` to split it down into 3 strings. I notice that on compile, with empty inputs, both month and year are undefined but day is not, thinking that could be where the issue may lie. – cts Aug 23 '21 at 14:36
  • OK but that must mean your component depends on what `dateInputValue` you pass to it, right? Are you always passing a "valid" value? – Sergiu Paraschiv Aug 23 '21 at 14:40
  • I guess we can either have a string, which originally looks like this: "28-03-2022" for example (if `dateInputValue` exists) *or* if it doesn't then we have `undefined` - I do notice in the latter case of it being undefined, and using console logs, that day is blank whilst month & year are both set to `undefined` – cts Aug 23 '21 at 14:43
  • 1
    There's no way `split` won't throw an exception on `undefined` so I guess it's sometimes an empty string? But this is most likely where your problem is, you're not handling "invalid" values for `dateInputValue` at all. – Sergiu Paraschiv Aug 23 '21 at 14:45
  • But if it were an empty string, then all 3 (DD/MM/YYYY) would return an empty string and not 2/3 returning `undefined` surely? – cts Aug 23 '21 at 14:48
  • Yes, exactly. That's why I'm saying you must be sending something funky in there. – Sergiu Paraschiv Aug 23 '21 at 15:02
  • I understand you're thinking, but I'm logging out that value so it's either `undefined` or a string like "28-07-2022". Thanks for your help though! – cts Aug 23 '21 at 15:04
  • 1
    If you are wanting to memoize a change handler, i.e. `onValueChange`, this should be done in a parent component passed as a stable reference. I agree with @SergiuParaschiv and don't see an issue with how the state is initialized. Perhaps the `dateInputValue` prop doesn't have the initial value you think it does. – Drew Reese Aug 23 '21 at 18:05

0 Answers0