У меня есть несколько наборов внутри объекта для разных типов питательных микроэлементов (витаминов, минералов, антиоксидантов, аминокислот и омега). Я хочу, чтобы каждый из них передавался как <option>
внутри своего собственного раскрывающегося меню, в котором отображается их собственный тип (например, витамины: витамин B2, B6, B5 и т. Д.)
Моя консоль показывает, что данные были успешно получены:
{vitamins: Array(6), minerals: Array(2), aminoacids: Array(1), antioxidants: Array(2), omegas: Array(1)}
Но когда я дохожу до Vitamins.js, где пытаюсь отобразить параметры, он говорит: «TypeError: vitamins.map не является функцией».
Вот мой файл res.json с моего сервера Express:
router.get('/', function(req, res, next) {
res.json({vitamins: [
{
name: "Vitamin B2"
},
{
name: "Vitamin B6"
},
{
name: "Vitamin B5"
}
],
minerals: [
{
name: "Calcium"
},
{
name: "Zinc"
}
]
});
});
Здесь объявляется состояние для res.json в Home.js. (Я знаю, что слово «пользователи» не имеет смысла прямо сейчас, и я изменю его. Просто пытаюсь сначала выяснить, почему это не работает.)
constructor(props) {
super(props);
this.state = {users: []};
}
componentDidMount() {
fetch('/users')
.then(res => res.json())
.then(users => this.setState({ users }));
}
render() {
return (
<MenuItems users={this.state.users} />
)
}
Это Menuitems.js, на один уровень ниже Home.js, где я вызываю функцию handleChange, поэтому, когда пользователь нажимает на новый микро (Vitamin B2 -> B6), новый микро (B6) становится новым выбранным параметром.
constructor(props) {
super(props);
this.state = {
value: '',
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
const { value } = e.target;
this.setState({
value: value
});
}
render() {
return (
<ul className="menuitems">
<li>
<Vitamins data={this.props.users} />
</li>
<li>
<Minerals data={this.props.users} />
</li>
</ul>
)
}
И это Vitamins.js (у меня также есть Minerals.js, AminoAcids.js и т. Д.), Где я пытаюсь сопоставить массив «витаминов» в моем объекте res.json и вытащить каждое имя внутри выделенного падать.
renderData() {
const vitamins = this.props.data;
console.log("the data", vitamins);
return vitamins.map((micro, index) => {
return (
<option value={micro.value} key={index}>{micro.name}</option>
)
})
}
render() {
return (
<form>
<select value={this.props.value} onChange={this.handleChange}>
<option value="" selected>--Vitamins--</option>
{this.renderData()}
</select>
</form>
)
}
Console.log в renderData () сначала ничего не покажет, но после componentDidMount () он показывает это ДВАЖДЫ
the data {vitamins: Array(6), minerals: Array(2), aminoacids: Array(1), antioxidants: Array(2), omegas: Array(1)}
ИЗМЕНИТЬ
Я последовал некоторым советам, которые мне дали, и попробовал применить их.
Этот сработал, где я объявил состояние внутри каждого дочернего компонента (витамины, минералы и т. Д.)
state = {users: []};
componentDidMount() {
fetch('/users')
.then(res => res.json())
.then(users => {
this.setState({
users: users.vitamins
});
})
}
renderData() {
const vitamins = this.state.users;
return vitamins.map((micro, index) => {
return (
<option value={micro.value} key={index}>{micro.name}</option>
)
})
}
Однако я не хочу постоянно получать данные в каждом компоненте. Я попытался объявить состояние в родительском MenuItems и передать {this.state.users.vitamins} в свойствах данных, как было предложено.
(MenuItems.js)
state = {users: []};
componentDidMount() {
fetch('/users')
.then(res => res.json())
.then(users => {
this.setState({
users
});
})
}
render() {
return (
<ul className="menuitems">
<li>
<Vitamins data={this.state.users.vitamins} />
</li>
</ul>
)
}
(Vitamins.js)
renderData() {
const vitamins = this.props.data;
return vitamins.map((micro, index) => {
return (
<option value={micro.value} key={index}>{micro.name}</option>
)
})
}
Но при этом я получаю «TypeError: Cannot read property 'map' of undefined», когда я делаю это.
Если я сделаю «const {vitamins} = this.props.data», я получу «TypeError: Cannot read property 'vitamins' of undefined».
Итак, как мне выполнить выборку на родительском уровне и передать единственный нужный мне массив в data =?
const { vitamins } = this.props.data
или:<Vitamins data={this.props.users.vitamins} />
+this.state = { users: {} };
- person Roy Wang   schedule 25.05.2018.map()
терпит неудачу. Сделайтеconsole.log(this.props)
в этой функции рендеринга витаминов, посмотрите, что вы на самом деле добавили, а затем вернитесь обратно. - person Mike 'Pomax' Kamermans   schedule 25.05.2018<Vitamins data={this.state.users.vitamins} />
, я вернусь undefined в console.log из функции рендеринга в Vitamins.js. Если я сделаю<Vitamins data={this.state.users} />
, я верну весь объект пользователей в console.log{vitamins: Array(6), minerals: Array(2), aminoacids: Array(1), antioxidants: Array(2), omegas: Array(1)}
. - person John White   schedule 25.05.2018this.state.users
перед сборкой Vitamins: скопируйте эту строку, выбросьте ВСЕ, что у вас есть, создайтеclass App extends React.Component { render() { let userstate = JSON.parse("...that string..."); return <Vitamins data={userstate}/>; } }
и посмотрите, что произойдет. Вот почему обычно советуют сформировать минимально воспроизводимый пример: почти ни один из показанного вами кода не требуется для на самом деле проверьте, что делает ваш витаминный класс. И если все в порядке, мы повторяем упражнение на один компонент выше (захватываем данные как JSON, загружаем их напрямую). - person Mike 'Pomax' Kamermans   schedule 26.05.2018