Я использую Semantic-UI-React в своем проекте React/Rails и пытаюсь использовать раскрывающееся меню Form.Select в более крупной форме внутри модального окна. Мне нужно получить значение .id (animal.id) из выбора, показывающего пользователя .name (animal.gnames) — gnmaes — это просто атрибут, который я использую в своих целях, чтобы избежать путаницы.
Я использую options= опору Form.Select, я сопоставляю массив элементов, а затем назначаю item.gname title, чтобы получить хороший выпадающий список имен для пользователя. Затем мне нужно получить идентификатор, который находится в этом большом массиве, и отправить его в запрос на выборку. Я пробовал каждую комбинацию реквизитов, но не могу получить идентификатор из массива и в то же время отображать имена.
Вот код. Я вырезал последнюю половину, так как она не имеет отношения к проблеме:
import React, { Component } from "react";
import { withRouter } from "react-router-dom"
import ActiveStorageProvider from 'react-activestorage-provider'
import { Menu, Button, Modal, Header, Icon, Image, Form, Input, Select, Label } from "semantic-ui-react"
import { Link } from "react-router-dom"
const value = null
const options = null
class Navigation extends Component {
state = { modalOpen: false,
title: "",
body: "",
animal: "",
geotag: false,
animals: []
};
componentDidMount() {
fetch('http://localhost:9000/api/v1/animals')
.then(r => r.json())
.then(animals => {
this.setState({ animals: animals })
})
};
handlechange = (event) => {
this.setState({ [event.target.name]: event.target.value })
};
submitForm = (event) => {
this.props.postSighting(this.state.title, this.state.body)
// NEED TO GET ANIMAL.ID IN HERE!!!
};
// THIS METHOD IS READY TO GO FOR DOING THE ITERATION AND SET STATE BUT COULD NOT GET IT OT WORK.
// HAD ISSUE WITH A FETCH AND SET STATE LOOP CALLS
selectAnimal = () => {
const mappedAnimals = this.state.animals.map(animal => {
this.setState({ animal: animal.gname })
})
return mappedAnimals
};
render () {
return (
//.......SKIP TO THE CODE THAT MATTERS
<Form.Select
label = "Animal"
name = "Animal"
onChange = {this.handlechange}
selection= // WHAT GOES HERE?
width = {8}
value= // WHAT GOES HERE?
compact
options = {this.state.animals.map(animal => ({
return
name: animal.id,
key: animal.id,
value: animal.id,
text: animal.gname
}))}
/> // HOW DO I GET ANIMAL.ID TO MY SUBMIT FORM FUNCTION?





Здесь много чего происходит, поэтому позвольте мне попытаться разобрать это по частям в комментариях к коду. Дайте мне знать, если что-то не ясно.
class Navigation extends Component {
state = {
modalOpen: false,
title: "",
body: "",
animal: "",
geotag: false,
animals: []
};
componentDidMount() {
fetch("http://localhost:9000/api/v1/animals")
.then(r => r.json())
.then(animals => {
this.setState({ animals: animals });
});
}
/**
* When a user selects an option in the dropdown, the following will happen:
* 1. this.handlechange gets called
* 2. Component's state gets updated to look like:
* {
* ...state,
* "Animal": <id of animal selected>
* }
* Side note: you will have to access this "Animal" value through this.state.Animal
* where the uppercase 'A' is very important. This is really prone to typos and not
* recommended. To fix this I would change your <Form.Select> to have a lowercase
* name attribute.
*/
handlechange = (event, { name, value }) => {
// We need to use { name, value } instead of event.target.name, etc
// due to how Semantic UI handles events. More info here:
// https://github.com/Semantic-Org/Semantic-UI-React/issues/638
this.setState({ [name]: value });
};
submitForm = event => {
this.props.postSighting(this.state.title, this.state.body);
// Recall from above that this.state.Animal contains the animal id currently selected
// so we can access it directly with this.state.Animal
const animalId = this.state.Animal;
// do stuff with animalId...
};
/**
* If this is called, it will destroy the array of animals you have in your state and replace it with a gname
* from one of the animals. You probably don't want this to happen.
* Not sure what you are trying to do here, what do you use the return value for?
* Also, this will return an array filled with 'undefined' since you don't return anything in the animals.map callback.
*/
selectAnimal = () => {
const mappedAnimals = this.state.animals.map(animal => {
this.setState({ animal: animal.gname });
});
return mappedAnimals;
};
render() {
return (
//.......SKIP TO THE CODE THAT MATTERS
<Form.Select
label = "Animal"
name = "Animal" // this is the name that gets passed to 'handlechange' as event.target.name
onChange = {this.handlechange}
// selection: this isn't a valid prop for Form.Select and will be ignored regardless of value
width = {8}
// value: we don't need to worry about this since Form.Select will handle it
compact
options = {this.state.animals.map(animal => ({
// return: was this a typo?
name: animal.id,
key: animal.id,
value: animal.id, // This is the value that gets passed to 'handlechange' as event.target.value
text: animal.gname
}))}
/>
);
}
}
оооо теперь вижу. Хорошо, да, извините, я новичок в React. Вы имеете в виду заглавное «Животное» в компоненте <Form.Select под «именем». Мне нужно изменить имя в инициализаторе состояния. Я понял теперь. Собираюсь попробовать.
Я все еще получаю «неопределенный» при вызове event.target.value в отладчике в handleChangeEvent
Все еще не в состоянии зафиксировать значение. Ааааааааааааааааааааааааааааа
Хорошо, я наконец понял. У меня не был правильный метод handleChangeEvent. Должно быть: handleChangeEvent = (e, { name, value }) => this.setState({ [name]: value })
Ах, я пропустил это, извините, обычно event.target.value будет работать, но только для собственных событий браузера. В этом случае собственное событие не запускается из-за реализации раскрывающегося списка в семантическом пользовательском интерфейсе. Подробнее см. github.com/Semantic-Org/Semantic-UI-React/issues/638
@miyu допустим, в объекте животного есть еще один ключ description. как description: animal.description, как бы вы могли обновить состояние с помощью клавиши description в той же функции handleChangeEvent?
@ DJ2 Немного сложно передать description напрямую handlechange, но вы можете использовать value в handlechange (животное id) для поиска в вашем списке животных, найти животное с соответствующим id и установить свое состояние, которое способ
После долгих исследований и некоторой помощи от @miyu оказалось, что это работает:
<Form.Select
fluid
onChange = {this.handleChangeEvent}
placeholder='select animal'
label = "Animal"
name = "animal"
width = {8}
selection
options = {this.state.animals.map(animal => ({
name: animal.gname,
key: animal.id,
value: animal.id,
text: animal.gname
}))}
/>
и ваш handleChangeEvent должен выглядеть так:
handleChangeEvent = (e, { name, value }) => this.setState({ [name]: value })
Хорошо, отлично, и я думаю, что это многое проясняет. Вопрос: откуда вы взяли
this.state.Animal? У меня естьthis.state.animal. Мне нужно изменить на верхний регистр? Я никогда раньше не слышал об этой функциональности с прописными буквами. Кроме того, как состояние обновляется с помощью раскрывающегося списка, если я явно не объявляю его в семантическом компонентеForm.Select?