React Native setState не вызывает рендеринга

Я полный новичок в реакции на нативную, и теперь я застрял с проблемой обновления. я использую react-native-paper а также typescript,

В моем приложении я хочу нажать кнопку, а затем текстовое поле должно изменить свой текст.

Проблема как-то в кнопке или вызываемой функции, потому что в журнале консоли ее всегда "before: true after:true" или же "before: false after:false", но я ожидал "before: true after: false" или же vice-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://stackru.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}
      />
    );
  }
}

2 ответа

Обновления состояния могут быть документацией асинхронного реагирования

Таким образом, вы не можете проверить свои console.log таким образом. Используйте функцию обратного вызова setState метод следующим образом,

this.setState({ connected: !this.state.connected }, () => {
        console.log("after: " + this.state.connected);
        console.log("--------------");
    });

Надеюсь, что это поможет вам.

Ваша проблема здесь,

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

setState является async функция, и требуется некоторое время, чтобы обновить состояние. Не блокирует выполнение следующих операторов. Таким образом, вы всегда получите предыдущее состояние только для 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 либо true или же false (Логическое), которое никогда не будет отображаться на экране. Если вы все еще хотите увидеть значение на экране, вы можете использовать это 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://stackru.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}
            />
        );
    }
}
Другие вопросы по тегам