开发者问题收集

来自 jsx 元素的 React 事件目标值未绑定到状态和 json 数组(类型错误无法读取未定义的属性)

2022-01-22
399

我正在尝试绑定来自 select 选项标签的事件的值,该标签具有从 mongodb 获取的位置数据,该数据在 componentDidMount() 生命周期方法调用期间填充在 select 下拉列表中。

我想要实现这样一种功能,当我从 select drop 中选择一个值时,应该填充来自其他 api(餐厅)的相应值。

但问题是获取 url 的承诺似乎没有解决,并没有绑定到 state.restaurants 数组以在输入类型文本框中创建 ul 元素。这是我的代码

export default class Vrestauranthome extends Component {
  constructor() {
    super();
    console.log('Home is called vrestaurant');
    this.state = {
      locations: [],
      restaurants: [],
    };
  }

  componentDidMount() {
    console.log('Wallpaper componentDidMount getting called....', this.state);

    fetch('http://localhost:5252/zomato/locations', { method: 'GET' })
      .then((response) => response.json())
      .then((data) => this.setState({ locations: data.data }));
  }

  fetchRestaurants = (event) => {
    fetch(`http://localhost:5252/zomato/restaurants/${event.target.value}`, {
      method: 'GET',
    })
      .then((response) => response.json())
      .then((data) => {
        this.setState({ restaurants: data.data });
        console.log(data.data);
      });
  };

  render() {
    if (!this.state.locations || !this.state.restaurants) {
      return <>Loading data...</>;
    }
    
    let locationList =
      this.state.locations.length &&
      this.state.locations.map((item) => (
        <option key={item.name} value={item.city_id}>
          {item.name}
        </option>
      ));

    let restaurantList = this.state.restaurants.length && (
      <ul>
        {this.state.restaurants.map((item) => (
          <li key={item.name}>{item.name}</li>
        ))}
      </ul>
    );

    return (
      <div className='ContainerHome'>
        <div className='location-selector' style={{ paddingLeft: '90px' }}>
          <select
            className='locationDropdown px-3'
            onChange={this.fetchRestaurants}
          >
            <option value='0' style={{ display: 'none' }}>
              Please type a location
            </option>
            {locationList}
          </select>
        </div>
        <div className='restaurantSelector' style={{ paddingLeft: '90px' }}>
          <input
            className='searchForRestaurantinputBOX'
            type='text'
            placeholder='  Search for restaurants'
            style={{
              paddingLeft: '50px',
              fontFamily: 'Poppins',
              opacity: '85%',
            }}
          />
          {restaurantList}
        </div>
      </div>
    );
  }
}

当我使用 fetch 方法通过 event.target.value 从 url 获取数据时,它会在我控制台记录它时显示该值,但它似乎没有与使用后端 api 路由从 mongodb DB 获取数据的 url 绑定。

这在 mongo db 中分别作为 Locations 和 Restaurants 集合。

我将 city_id 从 locations 映射到 Restaurants.city 以获取要在搜索输入框中填充的值。

[{"name":"ShalimarBhagh, Delhi","city_id":"1","location_id":"1","country_name":"India"}]

[{"name":"Gulab","city_name":"Delhi","city":"1","area":"11"}]

当我从下拉列表中选择一个选项时,它就会消失并引发以下错误: 它在浏览器中显示错误:未捕获的 TypeError:无法读取未定义的属性(读取“长度”)

当我从中选择某些内容时,检查浏览器中会显示以下内容: 在此处输入图片描述

2个回答

您应该在显示数据之前检查数据是否已加载。
render 方法中添加检查应该可以避免出现错误:

render() {
    if (!this.state.locations || !this.state.restaurants) {
      return <>Loading data...</>;
    }
    
    let locationList =
      this.state.locations.length &&
      this.state.locations.map((item) => (
        <option key={item.name} value={item.city_id}>
          {item.name}
        </option>
      ));

    let restaurantList = this.state.restaurants.length && (
      <ul>
        {this.state.restaurants.map((item) => (
          <li key={item.name}>{item.name}</li>
        ))}
      </ul>
    );

    ...
}

此外,请尝试像这样更改 setState 调用:

fetch('http://localhost:5252/zomato/locations', { method: 'GET' })
  .then((response) => response.json())
  .then((data) =>
    this.setState({
      ...this.state,
      locations: data.data,
    })
  );

...

fetch(`http://localhost:5252/zomato/restaurants/${event.target.value}`, {
  method: 'GET',
})
  .then((response) => response.json())
  .then((data) => {
    this.setState({ ...this.state, restaurants: data.data });
  });
lpizzinidev
2022-01-22

经过多次尝试并制作了与此相同的功能组件后,我发现了错误。

应该是 data => this.setState({restaurants:data.result}) 。它会在更新后返回结果。

这是因为在后端,它会在从 mongoose 模型获取数据后返回结果变量。嘘。

Vishal Torne
2022-01-24