Home > Software design >  Get data from an object that is sometimes null
Get data from an object that is sometimes null

Time:10-26

The site has a window (done with Dialog mui) that opens to get information (Device with id {} is at the user's) . There is a static text in this window (which is always present) and I want to finish off the text (in my case ID), which will change depending on the data.

My data is stored in the selectedItem object. But here the problem is, when the window (Dialog mui) is closed, then selectedItem === null.

Please tell me how to get ID correctly

export default function Table() {
  const records = useRecords(firestore)
  const [selectedItem, setSelectedItem] = useState();

  const handleClose = () => {
      setSelectedItem(null);
  }
    
  return (
    <div>
      <Dialog open={!!selectedItem} onClose={handleClose}>
        Device with id {} is at the user's
      </Dialog>

      {records.map((record) =>
        <TableCell record={record} 
                          onDeleteButtonPress={() => setSelectedItem(record)} 
                          key={record.id} />)}
          
    </div>
  )
}

CodePudding user response:

You can use another state to open/close that dialog accordingly. You can check the below code with my comments.

export default function Table() {
  const records = useRecords(firestore)
  const [selectedItem, setSelectedItem] = useState();
  //the new dialog state
  const [isDialogOpened, setIsDialogOpened] = useState(false);

  const handleClose = () => {
      //close the dialog manually with a state update
      setIsDialogOpened(false);
  }

  //when `selectedItem` is true, we will open the dialog
  React.useEffect(() => {
    if(selectedItem) {
       setIsDialogOpened(true)
    }
  }, [selectedItem])
    
  return (
    <div>
      <Dialog open={isDialogOpened} onClose={handleClose}>
        Device with id {} is at the user's
      </Dialog>

      {records.map((record) =>
        <TableCell record={record} 
                          onDeleteButtonPress={() => setSelectedItem(record)} 
                          key={record.id} />)}
          
    </div>
  )
}

If you don't want to have side-effects from useEffect, you can update isDialogOpened state in onDeleteButtonPress event as well.

export default function Table() {
  const records = useRecords(firestore)
  const [selectedItem, setSelectedItem] = useState();
  //the new dialog state
  const [isDialogOpened, setIsDialogOpened] = useState(false);

  const handleClose = () => {
      //close the dialog manually with a state update
      setIsDialogOpened(false);
  }
    
  return (
    <div>
      <Dialog open={isDialogOpened} onClose={handleClose}>
        Device with id {} is at the user's
      </Dialog>

      {records.map((record) =>
        <TableCell record={record} 
                          onDeleteButtonPress={() => {
         setSelectedItem(record);
         setIsDialogOpened(true); //open the dialog when `onDeleteButtonPress`
}} 
                          key={record.id} />)}
          
    </div>
  )
}

CodePudding user response:

One option is to use optional chaining (?.) to avoid trying to read id when selectedItem is undefined/null:

<Dialog open={!!selectedItem} onClose={handleClose}>
  Device with id {selectedItem?.id} is at the user's
</Dialog>

The problem is that React still evaluates its children even if the component they sit within (in this case Dialog) doesn't get rendered. That's because the above JSX code transpiles into the following React.createElement() function call:

React.createElement(Dialog, {
  open: !!selectedItem,
  onClose: handleClose
}, "Device with id ", selectedItem?.id, " is at the user's");

So each of the arguments need to be evaluated before createElement() is called, meaning that if you were to use selectedItem.id when selectedItem is null/undefined, JS would throw an error when this is evaluated. With optional chaining however, when selectedItem?.id is evaluated we get back undefined instead of JS throwing an error.

CodePudding user response:

You seem to be setting it to null on close? Just remove the

setSelectedItem(null) 

from the handle close. This should keep the state after closing the dialog.

  • Related