javascript - React JSX: velge "selected" på valgt <select> alternativ


I en React-komponent for en <select>-meny, må jeg sette selected-attributtet på alternativet som reflekterer apptilstanden.

I render() blir optionState sendt fra eieren av tilstanden til SortMenu-komponenten. Alternativverdiene blir sendt inn som props fra JSON.

render: function() {
  var options = [],
      optionState = this.props.optionState;

  this.props.options.forEach(function(option) {
    var selected = (optionState === option.value) ? ' selected' : '';

    options.push(
      <option value={option.value}{selected}>{option.label}</option>
    );
  });

// pass {options} to the select menu jsx

Dette utløser imidlertid en syntaksfeil ved JSX-kompilering.

Å gjøre dette fjerner syntaksfeilen, men løser åpenbart ikke problemet:

var selected = (optionState === option.value) ? 'selected' : 'false';

<option value={option.value} selected={selected}>{option.label}</option>

Jeg prøvde også dette:

var selected = (optionState === option.value) ? true : false;

<option value={option.value} {selected ? 'selected' : ''}>{option.label}</option>

Finnes det en anbefalt måte å løse dette på?

Svar #1

React gjør dette enda enklere for deg. I stedet for å definere selected på hvert alternativ, kan du (og bør) rett og slett skrive value={optionsState} på select-tagen selv:

<select value={optionsState}>
  <option value="A">Apple</option>
  <option value="B">Banana</option>
  <option value="C">Cranberry</option>
</select>

For mer info, se dokumentasjonen for React select-taggen.

Også forstår React automatisk boolske verdier for dette formålet, så du kan enkelt skrive (merknad: ikke anbefalt)

<option value={option.value} selected={optionsState == option.value}>{option.label}</option>

og det vil vise 'valgt' på riktig måte.

Svar #2

Du kan gjøre det React advarer deg mot når du prøver å sette «selected»-egenskapen til <option>:

Bruk defaultValue eller value props på <select> i stedet for å sette selected på <option>.

Så, du kan bruke options.value på defaultValue av din select

Svar #3

Her er en komplett løsning som inkluderer det beste svaret og kommentarene under det (som kan hjelpe noen som sliter med å sette alt sammen):

OPPDATERING FOR ES6 (2019) - bruker pilfunksjoner og objekt-destructuring

i hovedkomponenten:

class ReactMain extends React.Component {

  constructor(props) {
    super(props);
    this.state = { fruit: props.item.fruit };
  }

  handleChange = (event) => {
    this.setState({ [event.target.name]: event.target.value });
  }

  saveItem = () => {
    const item = {};
    item.fruit = this.state.fruit;
    // do more with item object as required (e.g. save to database)
  }

  render() {
    return (
      <ReactExample name="fruit" value={this.state.fruit} handleChange={this.handleChange} />
    )
  }

}

inkludert komponent (som nå er en stateless funksjonell):

export const ReactExample = ({ name, value, handleChange }) => (
  <select name={name} value={value} onChange={handleChange}>
    <option value="A">Apple</option>
    <option value="B">Banana</option>
    <option value="C">Cranberry</option>
  </select>
)

TIDLIGERE SVAR (ved bruk av bind):

i hovedkomponenten:

class ReactMain extends React.Component {

  constructor(props) {
    super(props);
    // bind once here, better than multiple times in render
    this.handleChange = this.handleChange.bind(this);
    this.state = { fruit: props.item.fruit };
  }

  handleChange(event) {
    this.setState({ [event.target.name]: event.target.value });
  }

  saveItem() {
    const item = {};
    item.fruit = this.state.fruit;
    // do more with item object as required (e.g. save to database)
  }

  render() {
    return (
      <ReactExample name="fruit" value={this.state.fruit} handleChange={this.handleChange} />
    )
  }

}

inkludert komponent (som nå er en stateless funksjonell):

export const ReactExample = (props) => (
  <select name={props.name} value={props.value} onChange={props.handleChange}>
    <option value="A">Apple</option>
    <option value="B">Banana</option>
    <option value="C">Cranberry</option>
  </select>
)

Hovedkomponenten opprettholder den valgte verdien for frukt (i tilstanden), den inkluderte komponenten viser valgt elementet, og oppdateringer sendes tilbake til hovedkomponenten for å oppdatere dens tilstand (som deretter går tilbake til den inkluderte komponenten for å endre den valgte verdien).

Merk bruken av en name-prop som lar deg erklære en enkelt handleChange-metode for andre felter på samme skjema uavhengig av hvilken type de har.

Svar #4

Jeg lagde en nedtrekksmeny for en språkutvelger - men jeg trengte at nedtrekksmenyen skulle vise gjeldende språk ved sideinnlasting. Jeg ville enten hente mitt opprinnelige språk fra en URL-parameter example.com?user_language=fr, eller oppdage det fra brukerens nettleserinnstillinger. Når brukeren så interagerte med nedtrekksmenyen, ville det valgte språket bli oppdatert, og språkvelgerens nedtrekksmeny ville vise det gjeldende valgte språket.

Siden hele denne tråden har gitt frukteksempler, har jeg alle slags fruktsgodt for deg.

  • Først, svar på det opprinnelig stilte spørsmålet med en enkel React-funksjonskomponent - to eksempler med og uten props, deretter hvordan man importerer komponenten andre steder.

  • Neste opp, det samme eksempelet - men oppgradert med Typescript.

  • Så en bonusavslutning - En språkvelger-dropdown-komponent som bruker Typescript.


Grunnleggende React (16.13.1) funksjonell komponenteksempel. To eksempler på FruitSelectDropdown, ett uten props og ett som aksepterer props fruitDetector

import React, { useState } from 'react'

export const FruitSelectDropdown = () => {
  const [currentFruit, setCurrentFruit] = useState('oranges')
  
  const changeFruit = (newFruit) => {
    setCurrentFruit(newFruit)
  }
  
  return (
    <form>
      <select 
        onChange={(event) => changeFruit(event.target.value)}
        value={currentFruit}
      >
        <option value="apples">Red Apples</option>
        <option value="oranges">Outrageous Oranges</option>
        <option value="tomatoes">Technically a Fruit Tomatoes</option>
        <option value="bananas">Bodacious Bananas</option>
      </select>
    </form>
  )
}

Eller du kan la FruitSelectDropdown akseptere props, kanskje har du en funksjon som gir en streng, du kan sende den gjennom ved å bruke fruitDetector-propen

import React, { useState } from 'react'

export const FruitSelectDropdown = ({ fruitDetector }) => {
  const [currentFruit, setCurrentFruit] = useState(fruitDetector)
  
  const changeFruit = (newFruit) => {
    setCurrentFruit(newFruit)
  }
  
  return (
    <form>
      <select 
        onChange={(event) => changeFruit(event.target.value)}
        value={currentFruit}
      >
        <option value="apples">Red Apples</option>
        <option value="oranges">Outrageous Oranges</option>
        <option value="tomatoes">Technically a Fruit Tomatoes</option>
        <option value="bananas">Bodacious Bananas</option>
      </select>
    </form>
  )
}

Importer deretter FruitSelectDropdown et annet sted i appen din

import React from 'react'
import { FruitSelectDropdown } from '../path/to/FruitSelectDropdown'

const App = () => {
  return (
    <div className="page-container">
      <h1 className="header">A webpage about fruit</h1>
      <div className="section-container">
        <h2>Pick your favorite fruit</h2>
        <FruitSelectDropdown fruitDetector='bananas' />

      </div>
    </div>
  )
}

export default App

FruitSelectDropdown med Typescript

import React, { FC, useState } from 'react'

type FruitProps = {
  fruitDetector: string;
}

export const FruitSelectDropdown: FC<FruitProps> = ({ fruitDetector }) => {
  const [currentFruit, setCurrentFruit] = useState(fruitDetector)
  
  const changeFruit = (newFruit: string): void => {
    setCurrentFruit(newFruit)
  }
  
  return (
    <form>
      <select 
        onChange={(event) => changeFruit(event.target.value)}
        value={currentFruit}
      >
        <option value="apples">Red Apples</option>
        <option value="oranges">Outrageous Oranges</option>
        <option value="tomatoes">Technically a Fruit Tomatoes</option>
        <option value="bananas">Bodacious Bananas</option>
      </select>
    </form>
  )
}

Importer deretter FruitSelectDropdown et annet sted i appen din

import React, { FC } from 'react'
import { FruitSelectDropdown } from '../path/to/FruitSelectDropdown'

const App: FC = () => {
  return (
    <div className="page-container">
      <h1 className="header">A webpage about fruit</h1>
      <div className="section-container">
        <h2>Pick your favorite fruit</h2>
        <FruitSelectDropdown fruitDetector='bananas' />

      </div>
    </div>
  )
}

export default App

Bonusrunde: Oversettelsesmeny med valgt nåværende verdi:

import React, { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'

export const LanguageSelectDropdown: FC = () => {
  const { i18n } = useTranslation()
  const i18nLanguage = i18n.language
  const [currentI18nLanguage, setCurrentI18nLanguage] = useState(i18nLanguage)
  
  const changeLanguage = (language: string): void => {
    i18n.changeLanguage(language)
    setCurrentI18nLanguage(language)
  }
  
  return (
    <form>
      <select 
        onChange={(event) => changeLanguage(event.target.value)}
        value={currentI18nLanguage}
      >
        <option value="en">English</option>
        <option value="de">Deutsch</option>
        <option value="es">Español</option>
        <option value="fr">Français</option>
      </select>
    </form>
  )
}

En uvurderlig ressurs for React/Typescript

Svar #5

Her er det nyeste eksemplet på hvordan man gjør det. Fra React-dokumentasjonen, pluss auto-binding og «fat-arrow»-metodesyntaks.

class FlavorForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};
  }

  handleChange = (event) =>
    this.setState({value: event.target.value});

  handleSubmit = (event) => {
    alert('Your favorite flavor is: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Pick your favorite flavor:
          <select value={this.state.value} onChange={this.handleChange}>
            <option value="grapefruit">Grapefruit</option>
            <option value="lime">Lime</option>
            <option value="coconut">Coconut</option>
            <option value="mango">Mango</option>
          </select>
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
} 

Svar #6

Hovedpoeng - Kontrollert komponent

Du ønsker å sette opp en "Kontrollert komponent". Dette vil kreve at du angir verdien på elementet i tillegg til å håndtere endringshendelsen for å oppdatere verdien.

https://reactjs.org/docs/forms.html#controlled-components

Eksempler

https://codepen.io/codyswartz/pen/QWqYNrY

Enkelt funksjonelt komponentvalgeksempel

Dette inkluderer også en standard og gjør den grå.

const defaultSelectValue = "Select a fruit"

const SelectExample = () => {
  const [selected, setSelected] = useState(defaultSelectValue)

  return (
    <>
      <label htmlFor="fruits">Fruits</label>{' '}
      <select
        id="fruits"
        name="fruits"
        defaultValue={selected}
        style={{ color: selected === defaultSelectValue ? "gray" : "black" }}
        onChange={e => setSelected(e.target.value)}
      >
        <option>{defaultSelectValue}</option>
        <option>Banana</option>
        <option>Apple</option>
        <option>Orange</option>
      </select>

      <h2>Selected: {selected}</h2>
    </>
  )
}

// Usage
<SelectExample />

Dynamisk gjenbrukbart eksempel med standard

Dette vil ta en samling av strenger som bruker den første som standard.

const SelectExample = ({ name, items }) => {
  const defaultSelectValue = items[0]
  const [selected, setSelected] = useState(defaultSelectValue)

  return (
    <>
      <label htmlFor={name}>{name}</label>{' '}
      <select
        id={name}
        name={name}
        defaultValue={selected}
        style={{ color: selected === defaultSelectValue ? "gray" : "black" }}
        onChange={e => setSelected(e.target.value)}
      >
        {items.map(item => (
          <option key={item} value={item}>
            {item}
          </option>
        ))}
      </select>

      <h2>Selected: {selected}</h2>
    </>
  )
}

// Usage
<SelectExample
  name="fruits"
  items={['Select a fruit', 'Banana', 'Apple', 'Orange']}
/>

Relaterte artikler