所以我一直在嘗試傳遞 API 呼叫的結果,但是在回傳結果的函式中,我檢查了是否按下了 Enter 或單擊了按鈕。現在,當我在提升狀態時通過此函式時,我收到此錯誤:
react-dom.development.js:11996 Uncaught TypeError: Cannot read properties of null (reading 'key')
at searchCity (Input.js:10:1)
at basicStateReducer (react-dom.development.js:16376:1)
at updateReducer (react-dom.development.js:16500:1)
at updateState (react-dom.development.js:16836:1)
at Object.useState (react-dom.development.js:17762:1)
at useState (react.development.js:1617:1)
at Weather (Weather.js:6:1)
at renderWithHooks (react-dom.development.js:16141:1)
at updateFunctionComponent (react-dom.development.js:20313:1)
at beginWork (react-dom.development.js:22356:1)
任何人都知道如何解決這個問題?
這是我的代碼:Input.js (child)
import { useRef } from "react";
import Data from '../config'
const Input = (props) => {
const userInput = useRef();
function searchCity(e) {
if (e.key === 'Enter' || e.type === "click") {
const inputValue = userInput.current.value;
console.log(inputValue)
fetch(Data.baseUrl1 inputValue)
.then ((response) => response.json())
.then (data => {
const cityData = data.data[0]
const lat = data.data[0].latitude
const lon = data.data[0].longitude
console.log(cityData, lat, lon)
getWeatherData(lat, lon, cityData)
})
}
}
function getWeatherData(latitude, longitude, geoData) {
fetch(Data.baseUrl2 latitude
"&lon=" longitude "&appid=" Data.key
"&exclude=current,minutely,hourly&units=metric")
.then((response) => response.json())
.then(data => {
return data;
})
}
return (
<div className="inputfield">
<input ref={userInput} onKeyDown={searchCity} type="text" placeholder="City name here..."/>
<button onClick={() => props.updateFetch(searchCity)}>Search</button>
</div>
)
}
export default Input;
Weather.js(父級)
import { useState } from "react";
import Input from "../components/Input";
const Weather = () => {
const [fetchedData, setFetchedData] = useState(null);
return (
<Input updateFetch={fetchdata => setFetchedData(fetchdata)}/>
)
}
export default Weather;
uj5u.com熱心網友回復:
檢查這一行 -
無法讀取 null 的屬性,讀取鍵。
這意味著 e 是您的物件,但 e.key 什么都不是,您正在嘗試閱讀 e.Key 也意味著 key 不是 e 物件的直接屬性。
我想應該是 e.target.key
您可以控制臺 log e 并找到它具有的所有屬性,然后過濾掉關鍵屬性的位置。
型別也是如此。
uj5u.com熱心網友回復:
我相信您在按下搜索按鈕時會遇到此問題,這有問題的 onClick 行為。當單擊搜索按鈕時searchCity,需要e事件引數的 立即被呼叫,但是您沒有將其傳遞進去,所以e是null,并且您收到錯誤Cannot read properties of null。您需要修改您的onClick函式以傳遞事件:onClick={(e) => props.updateFetch(searchCity(e))}.
uj5u.com熱心網友回復:
糾結的問題
提供的代碼存在很多問題。return之前沒有,getWeatherData所以.then回傳未定義。并不是說它真的很重要,因為一旦獲取了城市和天氣資料,您的組件就無處可存盤。
但是,最大的問題是您直接在組件中糾結 API 邏輯。通過將此代碼隔離在單獨的模塊中,您可以使組件更容易讀/寫,并且 API 函式可以在程式的其他區域中重用。注意使用URL和URLSearchParams避免使用字串構造 URL 并正確編碼 URL 子組件 -
// api/city.js
const BASE_URL = "https://api.citydata.com"
async function getCity(query) {
const u = new URL("/get", BASE_URL)
u.searchParams = new URLSearchParamas({ query })
// https://api.citydata.com/get?query=foobar
const {data} = await fetch(u).then(r => r.json())
return data[0]
}
export { getCity }
// api/weather.js
const BASE_URL = "http://weatherdata.org"
const APP_ID = "2c50fb2b94ae720g"
async function getWeather(lat, lon) {
const u = new URL("/json", BASE_URL)
u.searchParams = new URLSearchParams({
lat: lat,
lon: lon,
appid: APP_ID,
exclude: "current,minutely,hourly",
units: "metric"
})
// http://weatherdata.org/json?lat=1.23&lng=4.56&appid=2c50fb2b94ae720g&exclude=current,minutely,hourly&units=metric
return fetch(u).then(r => r.json())
}
export { getWeather }
受控組件
Search接下來我會說你的組件有一些問題。useRef一方面,在這種情況下沒有必要。onChange應該用于使您input成為受控組件并且onKeyDown可以用于檢測e.key == "Enter". 這是一個功能演示,您可以在瀏覽器中運行,看看它是如何作業的 -
// components/search.js
function Search() {
const [query, setQuery] = React.useState("")
const onSearch = e => {
console.log("search for:", query)
}
return <div>
<input
value={query}
onChange={e => setQuery(e.target.value)}
onKeyDown={e => e.key == "Enter" && onSearch(e)}
placeholder="enter a city name..."
/>
<button type="button" onClick={onSearch} children="??" />
</div>
}
ReactDOM.render(<Search />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
把它放在一起
現在簡化的Search組件正在作業并且api/city和api/weather模塊已經完成,讓我們將它們捆綁在一起onSearch。onSearch由于 API 模塊完成了繁重的作業,注釋大大簡化了 -
// components/search.js
import { getCity } from "../api/city.js"
import { getWeather } from "../api/weather.js"
function Search() {
const [query, setQuery] = React.useState("")
const [city, setCity] = React.useState(null)
const [weather, setWeather] = React.useState(null)
const onSearch = async e => {
try {
const city = await getCity(query)
const weather = await getWeather(city.latitude, city.longitude)
setCity(city)
setWeather(weather)
}
catch (err) {
console.error(err.message)
}
}
return <div>
<input
value={query}
onChange={e => setQuery(e.target.value)}
onKeyDown={e => e.key == "Enter" && onSearch(e)}
placeholder="enter a city name..."
/>
<button type="button" onClick={onSearch} children="??" />
{ city && weather
? [ <City city={city} />, <Weather weather={weather} /> ]
: null
}
</div>
}
最后定義加載時間City和狀態的組件Weather-cityweather
function City({ city }) {
return <div>{city.name} {city.state} {city.timezone} ...</div>
}
function Weather({ weather }) {
return <div>{weather.temp} {weather.timeOfDay} ...</div>
}
提升狀態
如果您想將此狀態提升到 Search更高的組件中,我建議您將city, weatherand onSearchup 移動到App并且僅onSearch向下傳遞到Search組件。注意更新onSearch接收一個query字串而不是一個事件 -
// components/app.js
import { getCity } from "../api/city.js"
import { getWeather } from "../api/weather.js"
import Search from "./search.js"
function App({
const [city, setCity] = React.useState(null)
const [weather, setWeather] = React.useState(null)
const onSearch = async query => {
try {
const city = await getCity(query)
const weather = await getWeather(city.latitude, city.longitude)
setCity(city)
setWeather(weather)
}
catch (err) {
console.error(err.message)
}
}
return <div>
<Search onSearch={onSearch} />
{ city && weather
? [ <City city={city} />, <Weather weather={weather} /> ]
: null
}
</div>
}
請注意,細微的區別是如何onSearch在更新的Search組件中呼叫 -
// components/search.js
function Search({ onSearch }) {
const [query, setQuery] = React.useState("")
return <div>
<input
value={query}
onChange={e => setQuery(e.target.value)}
onKeyDown={e => e.key == "Enter" && onSearch(query)}
placeholder="enter a city name..."
/>
<button type="button" onClick={e => onSearch(query)} children="??" />
</div>
}
PS 從不寫.then(data => data)。它完全沒有任何作用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/459691.html
標籤:反应
