javascript - Hvordan refererer jeg til dokumentet i React TypeScript?


Jeg vil gjøre dette i en av mine betingede funksjoner, men det gir fullstendig feil. Selv om jeg tildeler det til en variabel, sier det "kan ikke finne navnerommet 'document'"

document.getElementById("dropdown").selectedIndex = "1";

Og når jeg setter det inn i funksjonen min, sier det at objektet muligens er null, så hvordan refererer jeg til dette i en React TSX-fil?

Jeg har en select-setning som jeg trenger å dynamisk velge standardverdien for basert på noen betingelser. Hvis disse betingelsene er sanne, vil den kjøre denne dokumentvelgeren for å velge indeksen til den spesifiserte verdien. Jeg trenger bare å finne en måte å kjøre en funksjon som velger standardverdien for denne select-setningen, det er målet mitt.

<Select
    value={action}
    variant="outlined"
    classes={{ select: classes.selectOutlined }}
    id="dropdown"
    displayEmpty
    inputProps={{ 'aria-label': 'Action' }}
    onChange={(event) => handleActionChange(event.target.value as string)}
  >
    <MenuItem value="Action" disabled>
      Choose an Action
    </MenuItem>
    {actions.map((action) => {
      return <MenuItem key={action.text} value={action.text}>{action.text}</MenuItem>
    })}
  </Select>

Og så er dette funksjonen som oppretter disse menyvalgene, samt betingelsene for å sette standardverdien:

const actions = useMemo(() => {
  let allActions: Array<{ text: string, value: string }> = [
    { text: 'Notify SME for Review', value: 'sme' },
    { text: 'Return for Review', value: 'review' },
    { text: 'Notify Sales for Review', value: 'notify' },
    { text: 'Release to Agent', value: 'release' }
  ];

  if (groups.includes('SME')) {
    allActions = [{ text: 'Notify Sales for Review', value: 'notify' }, { text: 'Return for Review', value: 'review' },]
  } else if (groups.includes('IT')) {
    allActions = [{ text: 'Notify SME for Review', value: 'sme' },]
  } else if (groups.includes('Sales')) {
    allActions = [{ text: 'Release to Agent', value: 'release' }]
  }

  // This will select the second item in the select element when it's IT or Sales
  if (groups.includes('IT') || groups.includes('Sales')) {
    const dropdown = document.getElementById('dropdown')!.selectedIndex = "1";
  }

  return allActions;
}, [groups]);

Svar #1

Problemet du står overfor løses ved å forstå Reacts enveis dataflyt. Din sannhetskilde bør alltid komme ovenfra.

Med mer konkrete ord, ville du ikke lese eller skrive direkte til ditt #select-element, men i stedet ville du ha en tilstandsverdi for det, som ville være din kilde til sannhet:

const MyComponent = ({ groups }) => {
  const [selectedIndex, setSelectedIndex] = useState(0)  // or the default value

  /**
   * In here, you'll let react know that you want some code to run, when
   * this property changes in the outside world
   */
  useEffect(() => {
    if (groups.includes('IT') || groups.includes('Sales')) {
      setSelectedIndex(1)
    }
  }, [groups]);

  // ...

  return (
    <Select
      value={selectedIndex}
      ....other props...
    >
       ... children
    </Select>
  )
}

Egentlig bruker du ikke document.getElementId.

Svar #2

Du må fortelle TypeScript at du lager en nettleserapp via tsconfig.json. Du kan legge til en lib-egenskap med verdien dom. Et eksempel:

{
  "compilerOptions": {
    "lib": ["es5", "es6", "dom"], // <-- here
    "outDir": "./dist/",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es6",
    "moduleResolution": "node",
    "jsx": "react"
  },
  "include": ["./src/**/*"]
}

Dette vil tillate TypeScript å gjenkjenne document som et gyldig grensesnitt.

Når det er ute av veien, er en idiomatisk tilnærming for å velge DOM-noder i React-funksjonskomponenter med useRef.

import React, { useRef, useEffect } from 'react'

const SomeComponent = ({ innerRef }) => (
   <div ref={innerRef}>some div</div>
)

const ParentComponent = () => {
   const ref = useRef()

   useEffect(() => {
     if(ref.current) {
        console.log(ref.current.selectedIndex)
     }
   }, [ref.current])
   return <SomeComponent innerRef={ref} />
}

En ref trenger ikke å bli sendt fra en forelder. Den kan brukes i samme dokument. Jeg la det bare til i tilfelle brukstilfellet ditt krevde det.