Tìm kiếm trang web

javascript - React JSX: chọn "selected" trên tùy chọn <select> đã chọn


Trong một thành phần React cho menu <select>, tôi cần đặt thuộc tính selected trên tùy chọn phản ánh trạng thái của ứng dụng.

Trong render(), optionState được truyền từ chủ sở hữu trạng thái tới thành phần SortMenu. Các giá trị tùy chọn được truyền dưới dạng props từ 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

Tuy nhiên điều đó gây ra lỗi cú pháp khi biên dịch JSX.

Làm điều này sẽ loại bỏ lỗi cú pháp nhưng rõ ràng không giải quyết được vấn đề:

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

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

Tôi cũng đã thử điều này:

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

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

Có cách nào được khuyên để giải quyết vấn đề này không?

Câu trả lời #1

React làm điều này thậm chí còn dễ dàng hơn cho bạn. Thay vì định nghĩa selected trên mỗi tùy chọn, bạn có thể (và nên) chỉ cần viết value={optionsState} trên thẻ select:

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

Để biết thêm thông tin, xem tài liệu thẻ chọn React.

Ngoài ra, React tự động hiểu các giá trị boolean cho mục đích này, vì vậy bạn chỉ cần viết (lưu ý: không được khuyến nghị)

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

và nó sẽ xuất ra 'đã chọn' một cách phù hợp.

Câu trả lời #2

Bạn có thể làm theo những gì React cảnh báo khi bạn cố gắng thiết lập thuộc tính "selected" của <option>:

Sử dụng thuộc tính defaultValue hoặc value trên <select> thay vì đặt selected trên <option>.

Vì vậy, bạn có thể sử dụng options.value cho defaultValue của phần select của bạn

Câu trả lời #3

Đây là một giải pháp hoàn chỉnh kết hợp câu trả lời tốt nhất và các bình luận bên dưới nó (có thể giúp ai đó đang gặp khó khăn trong việc ghép tất cả lại với nhau):

CẬP NHẬT CHO ES6 (2019) - sử dụng hàm mũi tên và giải cấu trúc đối tượng

trong thành phần chính:

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} />
    )
  }

}

thành phần được bao gồm (hiện nay là một hàm không trạng thái):

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>
)

CÂU TRẢ LỜI TRƯỚC ĐÓ (sử dụng bind):

trong thành phần chính:

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} />
    )
  }

}

thành phần được bao gồm (hiện giờ là một chức năng không trạng thái):

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>
)

Thành phần chính duy trì giá trị được chọn cho trái cây (trong trạng thái), thành phần bao gồm hiển thị phần tử chọn và các cập nhật được gửi ngược trở lại thành phần chính để cập nhật trạng thái của nó (sau đó lại vòng về thành phần bao gồm để thay đổi giá trị được chọn).

Lưu ý việc sử dụng thuộc tính name cho phép bạn khai báo một phương thức handleChange duy nhất cho các trường khác trên cùng một biểu mẫu bất kể loại của chúng.

Câu trả lời #4

Tôi đang tạo một menu thả xuống cho bộ chọn ngôn ngữ - nhưng tôi cần menu thả xuống hiển thị ngôn ngữ hiện tại khi trang được tải. Tôi sẽ lấy ngôn ngữ ban đầu từ một tham số URL example.com?user_language=fr, hoặc phát hiện nó từ cài đặt trình duyệt của người dùng. Sau đó, khi người dùng tương tác với menu thả xuống, ngôn ngữ được chọn sẽ được cập nhật và menu thả xuống bộ chọn ngôn ngữ sẽ hiển thị ngôn ngữ hiện đang được chọn.

Vì cả chủ đề này đều đưa ra các ví dụ về trái cây, nên tôi có đủ mọi loại trái cây ngon lành cho bạn.

  • Trước hết, trả lời câu hỏi được đặt ra ban đầu với một component chức năng React cơ bản - hai ví dụ với và không có props, sau đó là cách import component đó ở nơi khác.

  • Tiếp theo, cùng một ví dụ - nhưng được tăng cường với Typescript.

  • Sau đó là một kết thúc thưởng - Một thành phần chọn ngôn ngữ dạng dropdown sử dụng Typescript.


Ví dụ về Component chức năng cơ bản của React (16.13.1). Hai ví dụ về FruitSelectDropdown, một ví dụ không có props và một ví dụ nhận 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>
  )
}

Hoặc bạn có thể để FruitSelectDropdown nhận props, có thể bạn có một hàm xuất ra chuỗi, bạn có thể truyền nó thông qua prop fruitDetector

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>
  )
}

Sau đó nhập FruitSelectDropdown ở nơi khác trong ứng dụng của bạn

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 với 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>
  )
}

Sau đó, nhập FruitSelectDropdown vào nơi khác trong ứng dụng của bạn

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

Vòng Thưởng: Menu thả xuống dịch với giá trị hiện tại được chọn:

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>
  )
}

Một nguồn tài nguyên vô giá cho React/Typescript

Câu trả lời số 5

Đây là ví dụ mới nhất về cách thực hiện điều đó. Từ tài liệu React, cộng với cú pháp phương thức "fat-arrow" tự động liên kết.

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>
    );
  }
} 

Câu trả lời số 6

Điểm chính - Thành phần được kiểm soát

Bạn đang muốn thiết lập một "Component Có Kiểm Soát". Điều này sẽ yêu cầu bạn đặt giá trị trên phần tử cũng như xử lý sự kiện on change để cập nhật giá trị.

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

Ví dụ

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

Ví dụ chọn thành phần chức năng đơn giản

Điều này cũng bao gồm một giá trị mặc định và làm mờ nó đi.

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 />

Ví dụ Tái sử dụng Động với Mặc định

Điều này sẽ lấy một tập hợp các chuỗi và sử dụng chuỗi đầu tiên làm mặc định.

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']}
/>

Bài viết liên quan