React Native 中的渲染会干扰变量更新

发布于 2025-01-11 23:42:47 字数 3508 浏览 3 评论 0原文

我用 React Native 编写了以下代码。可以看到,“componentDidMount”中的一个函数被调用(“getKey”),用于检索之前从存储中保存的一些变量:

export default class Cast extends Component {
constructor(props) {
 super(props);

 this.state = {
  admin: false,
  isPublishing: false,
  userComment: "",
  hasPermission: false,
  paused: true,
  _email: false,
  _name: false,
  _pword: false,
  _play_ID: false,
  _streamkey: false,
  _playurl: "",
  _streamurl: "",
  isLoading : true,
 };
}

getKey = async() => {
  try {
    var value = await AsyncStorage.getItem('email');
    this.setState({ _email: value });
    value = await AsyncStorage.getItem('playkey');
    this.setState({ _play_ID: value });
    const playurl = "https://stream.mux.com/" + value + ".m3u8"
    this.setState({ _playurl: playurl });
    value = await AsyncStorage.getItem('castkey');
    this.setState({ _streamkey: value });
    const streamurl = "rtmp://global-live.mux.com:5222/app/" + value
    this.setState({ _streamurl: streamurl });
    this.setState({ isLoading: false });
  } catch (error) {
    console.log("Error retrieving data" + error);
  }
}

componentDidMount(){
  this.getKey();
}

renderCameraView = () => {

  return (
    <NodeCameraView
      style={styles.nodeCameraView}
      /* eslint-disable */
      ref={vb => {
        this.vb = vb;
      }}
      /* eslint-enable */
      outputUrl = {this.state._streamurl}
      camera={settings.camera}
      audio={settings.audio}
      video={settings.video}
      autopreview
    />
  );
};

renderPlayerView = () => {

const { paused } = this.state;
const source = {
  uri: _playurl  //THROWS A "VARIABLE NOT FOUND" ERROR...LIKELY DUE TO RENDER BEFORE VALUE IS RETREIVED FROM STORAGE...?  
};
  return (
    <Video
      source={source} // Can be a URL or a local file.
      /* eslint-disable */
      ref={ref => {
        this.player = ref;
      }} // Store reference
      /* eslint-enable */
      onBuffer={this.onBuffer} // Callback when remote video is buffering
      onError={this.onError} // Callback when video cannot be loaded
      style={styles.nodePlayerView}
      fullscreen={false}
      resizeMode="cover"
      paused={paused}
    />
  );
};

renderEmptyView = () => {
  const { paused } = this.state;
  const source = {
    uri: "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"
  };

  return (
    <Video
      source={source} // Can be a URL or a local file.
      /* eslint-disable */
      ref={ref => {
        this.player = ref;
      }} // Store reference
      /* eslint-enable */
      onBuffer={this.onBuffer} // Callback when remote video is buffering
      onError={this.onError} // Callback when video cannot be loaded
      style={styles.nodePlayerView}
      fullscreen={false}
      resizeMode="cover"
      paused={paused}
    />
  );

};

//...

render() {
  const { admin, paused, isPublishing } = this.state;
  return (
    <View style={styles.container}>
     {isLoading ? this.renderEmptyView() : !isLoading && admin ? this.renderPlayerView() : !isLoading && !admin ? this.renderCameraView()} 


//...

    </View>
  );

//...

这段代码主要是操作性的。问题在于函数“renderPlayerView”立即被调用/渲染...如代码底部的“render”部分所示。据我了解...在 React Native 中,任何渲染都是在任何其他进程之前执行的。我相信这就是我的问题的原因。

“renderPlayerView”函数中的“uri: _playurl”行会抛出“找不到变量”错误或类似的错误。由于渲染是在其他任何事情之前执行的,我想这对我来说是有意义的,因为尚未从存储中检索“_playurl”变量的值。

因此我的问题是如何将正确的值(从“存储”检索后)传递给渲染后的“_playurl”变量?或者也许有某种解决方法?我预先感谢您的任何建议。

I have the following code written in React Native. As can be seen, a function within 'componentDidMount' is called ('getKey') that is used to retrieve some variables previously saved from storage:

export default class Cast extends Component {
constructor(props) {
 super(props);

 this.state = {
  admin: false,
  isPublishing: false,
  userComment: "",
  hasPermission: false,
  paused: true,
  _email: false,
  _name: false,
  _pword: false,
  _play_ID: false,
  _streamkey: false,
  _playurl: "",
  _streamurl: "",
  isLoading : true,
 };
}

getKey = async() => {
  try {
    var value = await AsyncStorage.getItem('email');
    this.setState({ _email: value });
    value = await AsyncStorage.getItem('playkey');
    this.setState({ _play_ID: value });
    const playurl = "https://stream.mux.com/" + value + ".m3u8"
    this.setState({ _playurl: playurl });
    value = await AsyncStorage.getItem('castkey');
    this.setState({ _streamkey: value });
    const streamurl = "rtmp://global-live.mux.com:5222/app/" + value
    this.setState({ _streamurl: streamurl });
    this.setState({ isLoading: false });
  } catch (error) {
    console.log("Error retrieving data" + error);
  }
}

componentDidMount(){
  this.getKey();
}

renderCameraView = () => {

  return (
    <NodeCameraView
      style={styles.nodeCameraView}
      /* eslint-disable */
      ref={vb => {
        this.vb = vb;
      }}
      /* eslint-enable */
      outputUrl = {this.state._streamurl}
      camera={settings.camera}
      audio={settings.audio}
      video={settings.video}
      autopreview
    />
  );
};

renderPlayerView = () => {

const { paused } = this.state;
const source = {
  uri: _playurl  //THROWS A "VARIABLE NOT FOUND" ERROR...LIKELY DUE TO RENDER BEFORE VALUE IS RETREIVED FROM STORAGE...?  
};
  return (
    <Video
      source={source} // Can be a URL or a local file.
      /* eslint-disable */
      ref={ref => {
        this.player = ref;
      }} // Store reference
      /* eslint-enable */
      onBuffer={this.onBuffer} // Callback when remote video is buffering
      onError={this.onError} // Callback when video cannot be loaded
      style={styles.nodePlayerView}
      fullscreen={false}
      resizeMode="cover"
      paused={paused}
    />
  );
};

renderEmptyView = () => {
  const { paused } = this.state;
  const source = {
    uri: "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"
  };

  return (
    <Video
      source={source} // Can be a URL or a local file.
      /* eslint-disable */
      ref={ref => {
        this.player = ref;
      }} // Store reference
      /* eslint-enable */
      onBuffer={this.onBuffer} // Callback when remote video is buffering
      onError={this.onError} // Callback when video cannot be loaded
      style={styles.nodePlayerView}
      fullscreen={false}
      resizeMode="cover"
      paused={paused}
    />
  );

};

//...

render() {
  const { admin, paused, isPublishing } = this.state;
  return (
    <View style={styles.container}>
     {isLoading ? this.renderEmptyView() : !isLoading && admin ? this.renderPlayerView() : !isLoading && !admin ? this.renderCameraView()} 


//...

    </View>
  );

//...

This code is mainly operative. The problem is that the function 'renderPlayerView' is immediately called/rendered...as can be seen in the 'render' section at the bottom of the code. As I understand...in React Native any render is performed BEFORE any other process. I believe this is the cause of my problem.

The 'uri: _playurl' line within the 'renderPlayerView' function throws a 'variable not found' error or something similar. Since the render is performed before anything else, I guess this makes sense to me as the value of the '_playurl' variable would not have yet been retrieved from storage.

Therefore my question is how could I pass the correct value (after retrieved from 'storage') to the '_playurl' variable FOLLOWING the render? Or perhaps there is some sort of work-around? I thank you in advance for any suggestions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

感性 2025-01-18 23:42:47

您应该为此创建一个加载器,只需创建一个状态并将其初始值设置为 true,一旦从异步存储中获取数据后将其设置为 false。然后你应该使用这个状态来有条件地渲染整个组件。

像这样:-

// 1. Create state
    state: {
    ...rest of your states,
    isLoading : true // ADD this   
    }

//2. Update state of isLoading once you are done fetching data
    getKey = async() => {
      try {
        ... your code
      } catch (error) {
        console.log("Error retrieving data" + error);
      } finally {
        this.setState({ loading: false });
     }
    }
    
//3. use the state to render your components conditionally
    
    render() {
      const { admin, paused, isPublishing, isLoading } = this.state;
      return (
        <View style={styles.container}>
          {isLoading  ?  <Loader/> //create some loader for your app (or simply use an activity indicator)
    : admin ? this.renderCameraView() : this.renderPlayerView()}  
    
    //...
    
        </View>
      );

You should create a loader for this, just create a state and set its initial value to true and once you're done fetching the data from async storage set it to false. Then you should use this state to conditionally render the whole component.

like this:-

// 1. Create state
    state: {
    ...rest of your states,
    isLoading : true // ADD this   
    }

//2. Update state of isLoading once you are done fetching data
    getKey = async() => {
      try {
        ... your code
      } catch (error) {
        console.log("Error retrieving data" + error);
      } finally {
        this.setState({ loading: false });
     }
    }
    
//3. use the state to render your components conditionally
    
    render() {
      const { admin, paused, isPublishing, isLoading } = this.state;
      return (
        <View style={styles.container}>
          {isLoading  ?  <Loader/> //create some loader for your app (or simply use an activity indicator)
    : admin ? this.renderCameraView() : this.renderPlayerView()}  
    
    //...
    
        </View>
      );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文