undefined 不是对象,加载后如何访问钩子刷新的对象
Undefined is not an object, how do I access object refreshed by hooks after it is loaded
在我的应用程序中,我输入了一个字符串,然后在 rest api 调用中立即调用该字符串,并根据输入的名称返回包含所有饮料的 json 对象。然后我想显示该对象的特定部分,例如名称,但在访问该对象的该部分时出现未定义错误,稍后我将详细说明。
我正在实现 react-navigation 和 react-elements,变量由 hooks 刷新。
export default class App extends Component {
render() {
console.log('change')
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
}
问题出在首页,我的代码可以在每个键入的字符后显示完整的对象:我可以显示包含我输入的查询名称的所有饮料的对象。但是,我想显示一个特定的对象中的元素,例如第一个 id (object.drinks[0].idDrink),我假设它还没有加载,并且出现了未定义的错误。我之前在没有钩子的情况下可以访问 id,那部分没有错。我假设我破坏了实现许多刷新我的应用程序的钩子的东西。
function HomeScreen() {
const [query, setQuery] = useState('');
const [jsonData, setJsonData] = useState([]);
const [loading, setLoading] = useState(true);
console.log(loading, '1')
useEffect(() => {
setLoading(true);
console.log(loading, '2')
fetch('https://www.thecocktaildb.com/api/json/v1/1/search.php?s=' + query, {
method: 'GET',
})
.then(response => response.json())
.then(jsonD => setJsonData(jsonD),
setLoading(false),
console.log(loading, '3'))
.catch(error => {
console.error(error);
});
}, [query])
return (
<ScrollView >
<Text>Bartender</Text>
<SearchBar
placeholder="Type Here..."
onChangeText={setQuery}
value={query}
/>
<>
{
loading ? console.log('waiting for loading') : console.log(jsonData.drinks[0].idDrink)
}
</>
</ScrollView >
);
}
我试图通过设置加载变量来解决这个问题,它会在对象完全加载后渲染它,但它并没有解决它。
如果我 运行 应用程序显示控制台日志而不是特定元素:
加载中? console.log('waiting for loading') : console.log('the data should be loaded'),
这是输出:
[Thu Dec 17 2020 20:20:07.902] LOG change
[Thu Dec 17 2020 20:20:08.159] LOG true 1
[Thu Dec 17 2020 20:20:08.175] LOG waiting for loading
[Thu Dec 17 2020 20:20:13.218] LOG true 2
[Thu Dec 17 2020 20:20:13.284] LOG true 3
[Thu Dec 17 2020 20:20:13.451] LOG false 1
[Thu Dec 17 2020 20:20:13.486] LOG the data should be loaded
[Thu Dec 17 2020 20:20:14.761] LOG false 1
[Thu Dec 17 2020 20:20:14.775] LOG the data should be loaded
在搜索栏中输入一个字符后,输出为:
[Thu Dec 17 2020 20:23:54.892] LOG false 1
[Thu Dec 17 2020 20:23:54.938] LOG the data should be loaded
[Thu Dec 17 2020 20:23:55.526] LOG false 2
[Thu Dec 17 2020 20:23:55.781] LOG false 3
[Thu Dec 17 2020 20:23:55.807] LOG false 1
[Thu Dec 17 2020 20:23:55.840] LOG the data should be loaded
[Thu Dec 17 2020 20:23:56.294] LOG false 1
[Thu Dec 17 2020 20:23:56.312] LOG the data should be loaded
TLDR:如何确保在完全加载后访问被钩子刷新的对象?
我建议您以不同的方式解决问题。
您可以将默认值设置为 null
:
,而不是将 jsonData
的默认值设置为数组
function HomeScreen() {
const [query, setQuery] = useState("");
const [jsonData, setJsonData] = useState(null);
useEffect(() => {
fetch("https://www.thecocktaildb.com/api/json/v1/1/search.php?s=" + query, {
method: "GET",
})
.then((response) => response.json())
.then((jsonD) => setJsonData(jsonD))
.catch((error) => {
console.error(error);
});
}, [query]);
return (
// ...
<>{jsonData && jsonData.drinks[0].idDrink}</>
// ...
);
}
这样您也不需要跟踪和更新 loading
状态。
您遇到的另一种方法的问题是,您无法确定 jsonData
状态在 loading
状态更新之前已经更新。
在我的应用程序中,我输入了一个字符串,然后在 rest api 调用中立即调用该字符串,并根据输入的名称返回包含所有饮料的 json 对象。然后我想显示该对象的特定部分,例如名称,但在访问该对象的该部分时出现未定义错误,稍后我将详细说明。 我正在实现 react-navigation 和 react-elements,变量由 hooks 刷新。
export default class App extends Component {
render() {
console.log('change')
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
}
问题出在首页,我的代码可以在每个键入的字符后显示完整的对象:我可以显示包含我输入的查询名称的所有饮料的对象。但是,我想显示一个特定的对象中的元素,例如第一个 id (object.drinks[0].idDrink),我假设它还没有加载,并且出现了未定义的错误。我之前在没有钩子的情况下可以访问 id,那部分没有错。我假设我破坏了实现许多刷新我的应用程序的钩子的东西。
function HomeScreen() {
const [query, setQuery] = useState('');
const [jsonData, setJsonData] = useState([]);
const [loading, setLoading] = useState(true);
console.log(loading, '1')
useEffect(() => {
setLoading(true);
console.log(loading, '2')
fetch('https://www.thecocktaildb.com/api/json/v1/1/search.php?s=' + query, {
method: 'GET',
})
.then(response => response.json())
.then(jsonD => setJsonData(jsonD),
setLoading(false),
console.log(loading, '3'))
.catch(error => {
console.error(error);
});
}, [query])
return (
<ScrollView >
<Text>Bartender</Text>
<SearchBar
placeholder="Type Here..."
onChangeText={setQuery}
value={query}
/>
<>
{
loading ? console.log('waiting for loading') : console.log(jsonData.drinks[0].idDrink)
}
</>
</ScrollView >
);
}
我试图通过设置加载变量来解决这个问题,它会在对象完全加载后渲染它,但它并没有解决它。
如果我 运行 应用程序显示控制台日志而不是特定元素:
加载中? console.log('waiting for loading') : console.log('the data should be loaded'),
这是输出:
[Thu Dec 17 2020 20:20:07.902] LOG change
[Thu Dec 17 2020 20:20:08.159] LOG true 1
[Thu Dec 17 2020 20:20:08.175] LOG waiting for loading
[Thu Dec 17 2020 20:20:13.218] LOG true 2
[Thu Dec 17 2020 20:20:13.284] LOG true 3
[Thu Dec 17 2020 20:20:13.451] LOG false 1
[Thu Dec 17 2020 20:20:13.486] LOG the data should be loaded
[Thu Dec 17 2020 20:20:14.761] LOG false 1
[Thu Dec 17 2020 20:20:14.775] LOG the data should be loaded
在搜索栏中输入一个字符后,输出为:
[Thu Dec 17 2020 20:23:54.892] LOG false 1
[Thu Dec 17 2020 20:23:54.938] LOG the data should be loaded
[Thu Dec 17 2020 20:23:55.526] LOG false 2
[Thu Dec 17 2020 20:23:55.781] LOG false 3
[Thu Dec 17 2020 20:23:55.807] LOG false 1
[Thu Dec 17 2020 20:23:55.840] LOG the data should be loaded
[Thu Dec 17 2020 20:23:56.294] LOG false 1
[Thu Dec 17 2020 20:23:56.312] LOG the data should be loaded
TLDR:如何确保在完全加载后访问被钩子刷新的对象?
我建议您以不同的方式解决问题。
您可以将默认值设置为 null
:
jsonData
的默认值设置为数组
function HomeScreen() {
const [query, setQuery] = useState("");
const [jsonData, setJsonData] = useState(null);
useEffect(() => {
fetch("https://www.thecocktaildb.com/api/json/v1/1/search.php?s=" + query, {
method: "GET",
})
.then((response) => response.json())
.then((jsonD) => setJsonData(jsonD))
.catch((error) => {
console.error(error);
});
}, [query]);
return (
// ...
<>{jsonData && jsonData.drinks[0].idDrink}</>
// ...
);
}
这样您也不需要跟踪和更新 loading
状态。
您遇到的另一种方法的问题是,您无法确定 jsonData
状态在 loading
状态更新之前已经更新。