开发者问题收集

未捕获(在承诺中)TypeError:无法读取未定义的属性(读取‘json’)

2022-07-03
1753

问题是,当我按下选择器来选择大洲时,它给了我这个错误/搜索购买方式工作正常,唯一的问题是选择器,这可能是因为我使用了 react-router-domV6 和 Axios 不知道

搜索购买方式工作正常 提前致谢 [1]: https://i.sstatic.net/US56E.png

Controls.jsx

import React from 'react';
        import { Search } from './Search';
        import {useState, useEffect} from "react";
        import {CustomSelect} from './CustomSelect';
        import styled from 'styled-components';
        const options=
       [
         {value: 'Америка',label: 'Америка'},
         {value: 'Європа',label: 'Європа'},
         {value: 'Азія',label: 'Азія'},
         {value: 'Африка',label: 'Африка'},
         {value: 'Океанія',label: 'Океанія'},
         {value: 'Австралія',label: 'Австралія'},
       ];
       const Wrapper=styled.div`
       display:flex;
       flex-direction:column;
       align-items:flex-start;
        @media (min-width: 768px) 
       {
         flex-direction:row;
         justify-content:space-between;
         align-items:center;
        }
       `;
         export const Controls = ({onSearch}) => {
          const [search,setSearch]=useState('');
          const [region,setRegion]=useState('');
          useEffect(()=>{
           const regionValue = region?.value;
           onSearch(search,regionValue);
          // eslint-disable-next-line
          },[search,region]);

        return (
         <Wrapper>
          <Search search={search} setSearch={setSearch}/>
           <CustomSelect
         options={options}
         placeholder='Континент'
         isClearable
         isSearchable={false}
         value={region}
         onChange={setRegion}
          />
        </Wrapper>
        );
      };

HomePage.jsx

import React from 'react';
     import axios from 'axios';
     import { useState, useEffect } from 'react';
     import { useNavigate,useParams } from 'react-router-dom';
     import { Main } from '../components/Main';
     import { Controls } from '../components/Controls';
     import { ALL_COUNTRIES } from '../config';
     import { List } from '../components/List';
     import { Card } from '../components/Card';
     import { Details } from './Details';

      export const HomePage = ({countries,setCountries}) => {
       const [filteredCountries,setFilteredCountries] = useState(countries);
       const  navigate  = useNavigate();
       const handleSearch =(search,region)=>{
       let data=[...countries];
       if(region){
        data=data.filter(c=>c.region.includes(region))
        }
        if(search){
          data=data.filter(c=>c.name.toLowerCase().includes(search.toLowerCase()))
        }
        setFilteredCountries(data);
        };
       useEffect(() => {
      if(!countries.lenght)
       axios.get(ALL_COUNTRIES).then(
        ({data})=>setCountries(data))
        .then(result => result.json)
        },[]);
        return (
         <>
           <Controls onSearch={handleSearch}/>
           <List>
        {
          filteredCountries.map((c)=>
          {
            const countryInfo={
              img:c.flags.png,
              name:c.name,
              info: [
                {
                  title:'Population',
                  description:c.population.toLocaleString(),
                },
                {
                  title:'Region',
                  description:c.region,
                },
                {
                  title:'Flag',
                  description:c.capital,
                },
              ],

             };
               return <Card key={c.name} onClick={(e)=>{navigate(`/country/${c.name}`)}} 
            {...countryInfo}/>
            })
           }
           </List>
           </>
           );
          };
2个回答

setCountries 函数返回 void。它不会为 Promise 链的下一个 then-able 返回任何内容。如果 countries 是一个数组,那么您在访问数组长度属性时也犯了一个错误。

useEffect(() => {
  if (!countries.lenght) // countries.lenght is false so resolves true always
    axios.get(ALL_COUNTRIES)
      .then(({ data }) => setCountries(data)) // setCountries returns undefined
      .then(result => result.json) // result is undefined
}, []);

也许您的意思是检查长度,然后返回 JSON Promise

示例:

useEffect(() => {
  if (!countries.length) {
    axios.get(ALL_COUNTRIES)
      .then(result => result.json()) // <-- invoke json()
      .then(({ data }) => setCountries(data));
  }
}, []);

如果我没有记错的话, axios 函数返回的 JSON 响应数据已经“解压”,因此 result.json() 调用可能没有必要。

useEffect(() => {
  if (!countries.length) {
    axios.get(ALL_COUNTRIES)
      .then(({ data }) => setCountries(data));
  }
}, []);
Drew Reese
2022-07-03

我找到了答案,我只是将 useEffect 拆分为搜索和选择器

useEffect(() => {
    if (!countries.length)
        axios.get(ALL_COUNTRIES).then(({ data }) => setCountries(data));
   // eslint-disable-next-line
}, []);


useEffect(() => {
    handleSearch();
  // eslint-disable-next-line
}, [countries]);

也许是由于 useEffect 限制

Michael Hamar
2022-07-04