Javascript 在将状态传递给我的useState钩子之后,它是未定义的,为什么?

Javascript 在将状态传递给我的useState钩子之后,它是未定义的,为什么?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在使用谷歌youtube api来流一些视频。不幸的是,当一个用户点击一个视频时,我在传递视频细节时被卡住了。 (我知道这个警告,我将很快通过在缩略图中添加索引来解决此问题) 问题是(它也在帖子的中间,但恐怕它会丢失):为什么HSS我的代码>搜索值。视频< /代码>改为未定义?< /P> 我得到了一个工作版本: 当我点击视频的缩略图时,我得到了预期的结果。 下面是它的代码: App.js import React, { useState, createContext } from &quo

我正在使用谷歌youtube api来流一些视频。不幸的是,当一个用户点击一个视频时,我在传递视频细节时被卡住了。 (我知道这个警告,我将很快通过在缩略图中添加索引来解决此问题)

问题是(它也在帖子的中间,但恐怕它会丢失):为什么HSS我的代码>搜索值。视频< /代码>改为未定义?< /P> 我得到了一个工作版本: 当我点击视频的缩略图时,我得到了预期的结果。

下面是它的代码:

App.js

import React, { useState, createContext } from "react";
import NavBar from "./NavBar";
import youtube from "../apis/youtube";
import VideoList from "./VideoList";
import VideoDetail from "./VideoDetail";

export const VideoContext = createContext();

function App() {
    const [ searchedValue, setSearchedValue ] = useState({ videos: [], selectedVideo: null });

    const API_KEY = process.env.REACT_APP_API_KEY;

    const handleSearch = async (inputText) => {
        const response = await youtube.get("/search", {
            params: {
                q: inputText,
                part: "snippet",
                type: "video",
                maxResults: 5,
                key: API_KEY
            }
        });
        setSearchedValue({ videos: response.data.items });
    };

    const handleSelectedVideo = (singleRenderedVideo) => {
        console.log("from App.js: ", singleRenderedVideo);
        // setSearchedValue({ selectedVideo: singleRenderedVideo });
    };

    return (
        <div className="ui container">
            <NavBar handleSearch={handleSearch} />
            <VideoContext.Provider value={handleSelectedVideo}>
                <p>I got {searchedValue.videos.length} results.</p>
                {/* <VideoDetail video={searchedValue.selectedVideo} /> */}
                <VideoList handleSelectedVideo={handleSelectedVideo} listOfVideos={searchedValue.videos} />
            </VideoContext.Provider>
        </div>
    );
}

export default App;
我得到以下错误:

const handleSelectedVideo = (singleRenderedVideo) => {
        // console.log("from App.js: ", singleRenderedVideo);
        setSearchedValue({ selectedVideo: singleRenderedVideo });
    };

整个App.js,其中的代码被更改

import React, { useState, createContext } from "react";
import NavBar from "./NavBar";
import youtube from "../apis/youtube";
import VideoList from "./VideoList";
import VideoDetail from "./VideoDetail";

export const VideoContext = createContext();

function App() {
    const [ searchedValue, setSearchedValue ] = useState({ videos: [], selectedVideo: null });

    const API_KEY = process.env.REACT_APP_API_KEY;

    const handleSearch = async (inputText) => {
        const response = await youtube.get("/search", {
            params: {
                q: inputText,
                part: "snippet",
                type: "video",
                maxResults: 5,
                key: API_KEY
            }
        });
        setSearchedValue({ videos: response.data.items });
    };

    const handleSelectedVideo = (singleRenderedVideo) => {
        // console.log("from App.js: ", singleRenderedVideo);
        setSearchedValue({ selectedVideo: singleRenderedVideo });
    };

    return (
        <div className="ui container">
            <NavBar handleSearch={handleSearch} />
            <VideoContext.Provider value={handleSelectedVideo}>
                <p>I got {searchedValue.videos.length} results.</p>
                <VideoDetail video={searchedValue.selectedVideo} />
                <VideoList handleSelectedVideo={handleSelectedVideo} listOfVideos={searchedValue.videos} />
            </VideoContext.Provider>
        </div>
    );
}

export default App;
import React,{useState,createContext}来自“React”;
从“/NavBar”导入导航栏;
从“./API/youtube”导入youtube;
从“/VideoList”导入视频列表;
从“/VideoDetail”导入VideoDetail;
export const VideoContext=createContext();
函数App(){
const[searchedValue,setSearchedValue]=useState({videos:[],selectedVideo:null});
const API_KEY=process.env.REACT_APP_API_KEY;
const handleSearch=async(inputText)=>{
const response=wait youtube.get(“/search”{
参数:{
问:输入文本,
部分:“片段”,
键入:“视频”,
最大结果:5,
密钥:API_密钥
}
});
setSearchedValue({videos:response.data.items});
};
const handleSelectedVideo=(singleRenderedVideo)=>{
//log(“from App.js:,singleRenderedVideo”);
setSearchedValue({selectedVideo:singleRenderedVideo});
};
返回(
我得到了{searchedValue.videos.length}结果

); } 导出默认应用程序;
searchedValue设置为{selectedVideo:…}。另一个属性,因为新值没有该属性。设置searchedValue时,应包括视频属性。在类组件中应该设置searchedValue({…searchedValue,selectedVideo:newValue})

如果设置状态并仅提供部分对象,react将与完整状态进行浅合并。这不会发生在功能组件中。不管你把状态设置成什么,那就是状态。所以这个代码:

setSearchedValue({ selectedVideo: singleRenderedVideo })
…将仅为具有selectedVideo属性的对象设置状态。它不再具有视频属性

您有两个选择:

  • 自己做一个简单的合并
  • 有两个独立的状态变量。对于像你这样的案例,我建议这样做

  • 非常感谢你的回答。但是,我还有一个关于#2的问题:在setSelectedVideo(singleRenderedVideo)中,您不使用selectedVideo的值。这样做可以吗?在您提供的代码中,新值与旧值无关,因此不需要使用旧值。如果您确实需要使用旧值(例如,因为您正在递增计数器),通常最好使用setState的函数版本,如
    setCount(prevCount=>prevCount+1)
    感谢您让我回到正确的方法。但是,在您的解决方案中,仅执行setSearchedValue({…searchedValue,selectedVideo:newValue})是不够的。Nicholas Tower使用setSearchedValue(previous=>({…previous,selectedVideo:singleRenderedVideo})提供的答案;作品
    import React from "react";
    import VideoItem from "./VideoItem";
    
    const VideoList = ({ listOfVideos }) => {
        const renderedListOfVideos = listOfVideos.map((video) => {
            return <VideoItem singleRenderedVideo={video} />;
        });
        return <div className="ui relaxed divided list">{renderedListOfVideos}</div>;
    };
    
    export default VideoList;
    
    const handleSelectedVideo = (singleRenderedVideo) => {
            // console.log("from App.js: ", singleRenderedVideo);
            setSearchedValue({ selectedVideo: singleRenderedVideo });
        };
    
    import React, { useState, createContext } from "react";
    import NavBar from "./NavBar";
    import youtube from "../apis/youtube";
    import VideoList from "./VideoList";
    import VideoDetail from "./VideoDetail";
    
    export const VideoContext = createContext();
    
    function App() {
        const [ searchedValue, setSearchedValue ] = useState({ videos: [], selectedVideo: null });
    
        const API_KEY = process.env.REACT_APP_API_KEY;
    
        const handleSearch = async (inputText) => {
            const response = await youtube.get("/search", {
                params: {
                    q: inputText,
                    part: "snippet",
                    type: "video",
                    maxResults: 5,
                    key: API_KEY
                }
            });
            setSearchedValue({ videos: response.data.items });
        };
    
        const handleSelectedVideo = (singleRenderedVideo) => {
            // console.log("from App.js: ", singleRenderedVideo);
            setSearchedValue({ selectedVideo: singleRenderedVideo });
        };
    
        return (
            <div className="ui container">
                <NavBar handleSearch={handleSearch} />
                <VideoContext.Provider value={handleSelectedVideo}>
                    <p>I got {searchedValue.videos.length} results.</p>
                    <VideoDetail video={searchedValue.selectedVideo} />
                    <VideoList handleSelectedVideo={handleSelectedVideo} listOfVideos={searchedValue.videos} />
                </VideoContext.Provider>
            </div>
        );
    }
    
    export default App;
    
    setSearchedValue({ selectedVideo: singleRenderedVideo })
    
    setSearchedValue(previous => ({
      ...previous,
      selectedVideo: singleRenderedVideo
    }));
    
    const [ videos, setVideos ] = useState([]);
    const [ selectedVideo, setSelectedVideo ] = useState(null);
    
    // ...
    
    setSelectedVideo(singleRenderedVideo);