Ala Eddine Menai
Ala Eddine Menai

Reputation: 2870

How to pass function as initial value of an object inside useState()?

I'm trying to migrate legacy code-base from class-based to function based using hooks.

The legacy code was like :

constructor(props){
    super(props)
    this.state = {
        pickerProps: {
            onPickDate: this.onPickDate,
            activeColor: "#119955",
            date: "12-12-2012"
        },
        inputStyle: "",
        selectedDate: null
    }
}

onPickDate = date => {
    this.setState((state) => ({
        selectedDate: date
    }))
}

onInputChange = (prop, value) => {
    this.setState((state) => ({ 
        pickerProps: {
            ...state.pickerProps,
            [prop]: value
        }
     }))
} 

changeInputStyle = e => {
    const value = e.target.value
    this.setState((state) => ({inputStyle: value}))
}

and the new code is :

const [inputStyle, setInputStyle] = useState("");
  const [selectedDate, setSelectedDate] = useState(null);
  const [pickerProps, setPickerProps] = useState({
    onPickDate:onPickDate, // How to pass function here
    activeColor: "#119955",
    date: "12-12-2012",
  });

  // This is the function I want to pass to useState()
  const onPickDate = (date) => {
    setSelectedDate(date);
  };

  const onInputChange = (prop, value) => {
    setPickerProps({ [prop]: value });
  };

  const changeInputStyle = (e) => {
    const value = e.target.value;
    setInputStyle(value);
  };

I receive a warning : The onPickDate was used before defined

Also when I send pickerProps to DatePicker :

 <div className="date-picker">
            <DatePicker {...pickerProps} />
          </div>

It invokes an error :

OnPickDate is not defined ()

Upvotes: 1

Views: 728

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281676

The problem here is related to function hoisting. The function you have declared is of type const and such variables with const or let declaration are not hoisted.

If you declare the function with function definition it will work without having to write it above useState

const [inputStyle, setInputStyle] = useState("");
  const [selectedDate, setSelectedDate] = useState(null);
  const [pickerProps, setPickerProps] = useState({
    onPickDate:onPickDate, // How to pass function here
    activeColor: "#119955",
    date: "12-12-2012",
  });

  function onPickDate(date) {
    setSelectedDate(date);
  };

  const onInputChange = (prop, value) => {
    setPickerProps({ [prop]: value });
  };

  const changeInputStyle = (e) => {
    const value = e.target.value;
    setInputStyle(value);
  };

However you need to store functions in state as it will make it difficult for you to update state, you can directly pass them as props to children

const [inputStyle, setInputStyle] = useState("");
  const [selectedDate, setSelectedDate] = useState(null);
  const [pickerProps, setPickerProps] = useState({
    activeColor: "#119955",
    date: "12-12-2012",
  });

  // This is the function I want to pass to useState()
  const onPickDate = (date) => {
    setSelectedDate(date);
  };

  const onInputChange = (prop, value) => {
    setPickerProps({ [prop]: value });
  };

  const changeInputStyle = (e) => {
    const value = e.target.value;
    setInputStyle(value);
  };

  return (
       <div className="date-picker"> 
            <DatePicker {...pickerProps} onPickDate ={onPickDate}/>
          </div>
  }

Upvotes: 2

Related Questions