You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS中将CamSelect选中值传递给VideoStream实现视频切换

问题原因
  1. localStorage的变更不会触发React组件重渲染,VideoStream组件仅在首次渲染时读取一次localStorage的值,后续localStorage更新后组件感知不到,不会重新拉取url渲染播放器。
  2. CamSelect组件中setState是异步操作,原代码在componentDidMount里调用setState后立刻读取this.state.selected拿到的还是更新前的空值,写入localStorage的初始值本身就是错误的。
解决方案

采用状态提升实现组件通信,是当前场景下成本最低的实现方式:将选中的摄像头流地址状态放到两个组件的公共父组件中维护,通过props传递状态和更新回调,实现状态变更的同步响应。


步骤1:修改公共父组件(示例为App.js,即CamSelect和VideoStream的共同上层组件)

import React, { useState } from 'react';
import CamSelect from './CamSelect';
import VideoStream from './VideoStream';

function App() {
  // 公共状态存储选中的摄像头流地址
  const [selectedCamUrl, setSelectedCamUrl] = useState('');

  return (
    <div className="App">
      {/* 把更新url的方法传给CamSelect */}
      <CamSelect onUrlChange={setSelectedCamUrl} />
      {/* 把当前选中的url传给VideoStream */}
      <VideoStream url={selectedCamUrl} />
    </div>
  );
}

export default App;

步骤2:修改CamSelect.js

移除内部状态的单独维护,切换/初始化选项时通过props回调通知父组件更新公共状态:

import React from "react";
import { Select, MenuItem, FormControl, InputLabel } from "@material-ui/core";
import "./CamSelect.css"

export default class CamSelect extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        currentCity: localStorage.getItem("city"),
        data: [
            {
                location: "abc",
                link: [
                    {name: "cam1", url: "https://...."},
                    {name: "cam2", url: "https://...."}
                ]
                
            },
            {
                location: "xyz",
                link: [
                  {name: "cam1", url: "https://...."},
                ]
                
            },
        ],
        selected: '',
    };

  }

  componentDidMount ()  {
    this.state.data.map(ur => {
      if(this.state.currentCity == ur.location){
        const defaultUrl = ur.link[0].url;
        this.setState({selected: defaultUrl})
        // 初始化时把默认url同步给父组件
        this.props.onUrlChange(defaultUrl);
      }
    })
  }
  handleChange = (event) => {
    const newUrl = event.target.value;
    this.setState({ selected: newUrl, name: event.target.name });
    // 切换选项时把新url同步给父组件
    this.props.onUrlChange(newUrl);
  };
  
  renderOptions() {
    return this.state.data.map((dt, i) => {
      if(this.state.currentCity == dt.location){
        return dt.link.map((lnk, index) => {
        return (
            <MenuItem
                label="Select a camera"
                value={lnk.url}
                key={index}
                name={lnk.name}
            >
                {lnk.name}
            </MenuItem>
             )
            })
            }
          }
    )
  };

  render() {
    return (
      <FormControl className="camera-select" style={{ minWidth: "100px"}}>
        <InputLabel id="demo-simple-select-label" style={{color:"white"}}>Camera</InputLabel>
        <Select
          labelId="demo-simple-select-label"
          id="demo-simple-select"
          className="camera-text-color"
          value={this.state.selected}
          onChange={this.handleChange}
        >
          {this.renderOptions()}
        </Select>
      </FormControl>
    );
  }
}

步骤3:修改VideoStream.js

直接读取props传入的url即可,props变化会自动触发组件重渲染,更新播放器地址:

import React from 'react';
import ReactPlayer from 'react-player';
import { 
    Card, 
    CardContent } from '@material-ui/core';
import "./VideoStream.css"

// 接收父组件传入的url参数
const VideoStream = ({url}) => {
       return (
         <Card className="video-player">
          <label className="video-label">Live Feed </label>
             <CardContent className="video-cardContent">
               <ReactPlayer
                  url= {url}
                  width="100%"
                  height="250px"
                  playing={true}
                  muted={true}
                  controls
                  className="hls-player"
               /> 
            </CardContent>
          </Card>
       );
     };
export default VideoStream;

如果两个组件的层级相差很大,逐层传递props比较繁琐,也可以用React Context来共享选中的url状态,不需要额外引入第三方状态管理库。

内容的提问来源于stack exchange,提问作者Vishal K.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:27:03