0

I'm using React hooks and trying to set the initial state of a constant inside a component with the passed down props. I've seen multiple examples of this online, but when I do it, the array destructuring returns the whole props object, not the instance I want.

Import React, {useState} from "react";

const MyComponent = (props) => {
   console.log(props) // {date: "2019-11-26", task: "cooking"}
   const [date, setDate] = useState(props);
   console.log(date) // {date: "2019-11-26, task: "cooking"}

   return (...)
}

export default MyComponent;

I'd assume that with object/array destructuring the value of date would automatically be assigned the value from props (the string "2019-11-26"), not the whole props object. What am I missing? I can get around this by setting const [date, setDate] = useState(props.date) but that breaks eslints react plugins destructuring rule and I'd like to avoid it.

Edit

Thanks to helloitsjoe for an answer that solves my problem!

P4nd4b0b3r1n0
  • 1,951
  • 3
  • 22
  • 31
  • What does actually fail here? – kind user Nov 26 '19 at 12:54
  • *"What am I missing?"* The value of the state is whatever you pass to `useState` and/or `setDate`. `useState` returns an array with two values: The current value of the state and a function to update the state. That has nothing to do with the structure of the value you store in the state. – Felix Kling Nov 26 '19 at 12:54
  • *"but that breaks eslints react plugins destructuring rule and I'd like to avoid it."* Did you look at the solutions provided in the documentation for that rule? – Felix Kling Nov 26 '19 at 12:56

5 Answers5

2

You can destructure props in the argument definition. Note that it's best practice if you're setting state from props to name the prop initialX or defaultX to indicate that it's being set in state, and the state should be used from that point on.

const MyComponent = ({ initialDate }) => {
  const [date, setDate] = useState(initialDate);

  ...
}
helloitsjoe
  • 6,264
  • 3
  • 19
  • 32
  • 2
    Thanks this works and the comment on the naming best practices was valuable. – P4nd4b0b3r1n0 Nov 26 '19 at 13:04
  • For avoid change the initial value and respect immutability in case of objects, a copy should be done, and fastest way is use the spread operator ( const [date, setDate] = useState(...initialDate); – Carmine Tambascia Jul 09 '21 at 11:28
  • It's not necessary to make a copy of an object when setting it as initial state, `setDate` will handle updates immutably. In your example, assuming you mean `useState({...initialDate})`, this would only work if `initialDate` is an object, but again would be unnecessary. – helloitsjoe Jul 09 '21 at 13:25
2

you need to destructure the props like so:

const MyComponent = ({date, task}) => {
   const [myDate, setMyDate] = useState(date);
  console.log(myDate); //get the date here
}

blueseal
  • 2,726
  • 6
  • 26
  • 41
0

You can do this like:

Import React, {useState} from "react";

const MyComponent = (props) => {
   const {date} = props //destructing
   console.log(props) // {date: "2019-11-26", task: "cooking"}
   const [date, setDate] = useState(date);
   console.log(date) 
   return (...)
}

export default MyComponent;

OR

Import React, {useState} from "react";

    const MyComponent = ({date}) => { //destructing
       const [date, setDate] = useState(date);
       console.log(date) 

       return (...)
    }

    export default MyComponent;
bakar_dev
  • 936
  • 4
  • 13
  • Just wanted to point that your first example would give an error because `date` would be declared twice – DerpyNerd Nov 21 '20 at 13:51
0

You have to destructure the props for the destructuring to actually work.

try

const MyComponent = ({date, task}) => {
   ....
}
aaKhan
  • 247
  • 2
  • 16
0

In case the date property is inside an object you should follow this approach:

import "./styles.css";
import React, { useState } from "react";

const basket = {
  apples: 10,
  banana: 5
};

const SimpleComp = () => {
  const [{ apples, banana }, setBasket] = useState({ ...basket });

  return (
  <div>
    <button
      onClick={() =>
        setBasket((currentState) => ({
          ...currentState,
          apples: currentState.apples + 1,
          banana: currentState.banana + 1
        }))
      }
    >
    Add Fruit
    </button>
    <div> Apples : {apples} </div>
    <div> Banana : {banana} </div>
  </div>
 );
};

 export default SimpleComp; 

where to useState is been provided a copy of basket thus respecting immutability, try yourself code Sandbox

or in case of simple date variable:

import "./styles.css";
import React, { useState } from "react";

const actualDate = new Date()
const actualDateToday = actualDate.getDate()
console.log(actualDateToday);

const MyComponent = () => {
  console.log(actualDate) // {date: "2019-11-26", task: "cooking"}
  const [date, setDate] = useState(actualDateToday);
  console.log(date) // {date: "2019-11-26, task: "cooking"}
    
  return (   
    <div>
       <p> Date Today: {actualDateToday} </p>
      <button 
         onClick={() => setDate(date => date + 1)} >
         Add a day
      </button>
  
    <p> Date Tomorrow: {date}</p>

    </div>  
  );
 }
 export default MyComponent

try here code Sandbox

Carmine Tambascia
  • 1,628
  • 2
  • 18
  • 32