首页 > 解决方案 > React Native setState 不会导致渲染

问题描述

我是 react native 的完整初学者,现在我遇到了更新问题。我正在使用react-native-papertypescript

在我的应用程序中,我想按下一个按钮,然后文本字段应该更改其文本。

问题出在按钮或被调用函数上,因为在控制台日志中它总是"before: true after:true"or "before: false after:false",但我期望的是"before: true after: false"orvice-versa

我还有第二个文本视图,它根本没有显示。

也许有人可以告诉我我做错了什么?

我的 index.js

import * as React from 'react';
import { AppRegistry } from 'react-native';
import { Provider as PaperProvider } from 'react-native-paper';
import App from './src/App';

export default function Main() {
  return (
    <PaperProvider>
      <App />
    </PaperProvider>
  );
}

AppRegistry.registerComponent('main', () => Main);

我的 MyNavigation.tsx(目前包含我的整个应用程序)。

import * as React from 'react';
import { BottomNavigation, Text, Avatar, Button, Card, Title, Paragraph, Banner } from 'react-native-paper';
import { View, Image, WebView } from 'react-native';

export default class MyNavi extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.setUnConnected = this.setUnConnected.bind(this);
  }

  state = {
    index: 0,
    routes: [
      { key: 'viewcamera', title: 'View', icon: 'remove-red-eye' },
      { key: 'viewsettings', title: 'Settings', icon: 'settings' },
      { key: 'viewhelp', title: 'How-To', icon: 'help' },
    ],
    visible: true,
    connected: false,
  };

  _handleIndexChange = index => { this.setState({ index }); }

  setUnConnected = function () {
    console.log("before: " + this.state.connected);
    this.setState({ connected: !this.state.connected });
    console.log("after: " + this.state.connected);
    console.log("--------------");
  };

  ViewRoute = () =>
    <View style={{ flex: 1, marginTop: 40 }}>

      {/* --------- This text field does not get updated -------------*/}
      <Text>connected: {this.state.connected ? 'true' : 'false'}</Text>

      {/* --------- This text field is not shown at all ------------*/}
      <Text>
        {this.state.connected}
      </Text>

      <Button icon="camera" mode="contained" onPress={this.setUnConnected}>
        Press me
      </Button>

      <View style={{ height: 400, width: 400 }}>
        <WebView
          source={{ uri: 'https://stackoverflow.com/' }}
          style={{ marginTop: 40 }}
        // onLoad={() => this.setState({ connected: true })}
        />
      </View>
    </View>

  SettingsRoute = () => <Text>Settings</Text>;

  HelpRoute = () => <View></View>

  _renderScene = BottomNavigation.SceneMap({
    viewcamera: this.ViewRoute,
    viewsettings: this.SettingsRoute,
    viewhelp: this.HelpRoute,
  });

  render() {
    return (
      <BottomNavigation
        navigationState={this.state}
        onIndexChange={this._handleIndexChange}
        renderScene={this._renderScene}
      />
    );
  }
}

标签: reactjsreact-nativereact-native-paper

解决方案


你的问题来了

setUnConnected = function () {
    console.log("before: " + this.state.connected);
    this.setState({ connected: !this.state.connected });
    console.log("after: " + this.state.connected);
    console.log("--------------");
};

setStateasync函数,更新状态需要一些时间。它不会阻止下一条语句的执行。因此,您将始终只为两个console.log.

要获取实际更新的值,您应该在 setState 中使用回调。

setUnConnected = function () {
    console.log("before: " + this.state.connected);
    this.setState({ connected: !this.state.connected }, () => console.log("after: " + this.state.connected); );   //Now you will get updated value.

    console.log("--------------");
};

为了这,

{/* --------- This text field is not shown at all ------------*/}
<Text>
   {this.state.connected}
</Text>

this.state.connected要么是要么truefalse布尔值),它永远不会显示在屏幕上。如果您仍想在屏幕上看到该值,则可以使用 this hack

<Text>
   {this.state.connected.toString()}
</Text>

更新

文档中,

页面是延迟渲染的,这意味着页面将在您第一次导航到它时被渲染。初始渲染后,所有页面都保持渲染状态以保持其状态。

取而代之的是,

_renderScene = BottomNavigation.SceneMap({
    viewcamera: this.ViewRoute,
    viewsettings: this.SettingsRoute,
    viewhelp: this.HelpRoute,
});

你应该使用这个版本的renderScene,

_renderScene = ({ route, jumpTo }) => {
  switch (route.key) {
    case 'viewcamera':
      return <ViewRoute jumpTo={jumpTo} connected={this.state.connected} setUnConnected={this.setUnConnected}/>;  //Here you can pass data from state and function to your component
    case 'viewsettings':
      return <SettingsRoute jumpTo={jumpTo} />;
    case 'viewhelp':
      return <HelpRoute jumpTo={jumpTo} />;
  }
}

您的完整代码应如下所示,

import * as React from 'react';
import { BottomNavigation, Text, Avatar, Button, Card, Title, Paragraph, Banner } from 'react-native-paper';
import { View, Image, WebView } from 'react-native';

const ViewRoute = (props) =>
  <View style={{ flex: 1, marginTop: 40 }}>

    {/* --------- This text field does not get updated -------------*/}
    <Text>connected: {props.connected ? 'true' : 'false'}</Text>

    {/* --------- This text field is not shown at all ------------*/}
    <Text>
      {props.connected.toString()}
    </Text>

    <Button icon="camera" mode="contained" onPress={props.setUnConnected}>
      Press me
    </Button>

    <View style={{ height: 400, width: 400 }}>
      <WebView
        source={{ uri: 'https://stackoverflow.com/' }}
        style={{ marginTop: 40 }}
      // onLoad={() => this.setState({ connected: true })}
      />
    </View>
  </View>

const SettingsRoute = () => <Text>Settings</Text>;

const HelpRoute = () => <View></View>

export default class MyNavi extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.setUnConnected = this.setUnConnected.bind(this);
    }

    state = {
        index: 0,
        routes: [
            { key: 'viewcamera', title: 'View', icon: 'remove-red-eye' },
            { key: 'viewsettings', title: 'Settings', icon: 'settings' },
            { key: 'viewhelp', title: 'How-To', icon: 'help' },
        ],
        visible: true,
        connected: false,
    };

    _handleIndexChange = index => { this.setState({ index }); }

    setUnConnected = function() {
        console.log("before: " + this.state.connected);
        this.setState({ connected: !this.state.connected });
        console.log("after: " + this.state.connected);
        console.log("--------------");
    };

    _renderScene = ({ route, jumpTo }) => {
        switch (route.key) {
            case 'viewcamera':
                return <ViewRoute jumpTo={jumpTo} connected={this.state.connected} setUnConnected={this.setUnConnected}/>; //Here you can pass data from state and function to your component
            case 'viewsettings':
                return <SettingsRoute jumpTo={jumpTo} />;
            case 'viewhelp':
                return <HelpRoute jumpTo={jumpTo} />;
        }
    }

    render() {
        return (
            <BottomNavigation
              navigationState={this.state}
              onIndexChange={this._handleIndexChange}
              renderScene={this._renderScene}
            />
        );
    }
}

推荐阅读