在NavigationOptions React本机内部调用setstate

时间:2019-05-29 11:27:48

标签: reactjs react-native react-navigation

我正在尝试更改navigationOptions中的状态值。

我的导航选项

static navigationOptions = ({ navigation }) => {
    const { params = {} } = navigation.state;
   // alert(params.searchText);
    return {
      headerLeft: (params.searchText) ? <View
        style={{
          flexDirection:
            'row', justifyContent: 'center'
        }}>
        <TouchableOpacity
          onPress={()=> {
            // navigation.navigate('home');
            alert('Coming soon ');
          }}>
          <Image style={{ marginLeft: 20, height: 20, width: 20, resizeMode: "contain" }}
            source={require('../assets/header_icons/three_logo.png')}
          />
        </TouchableOpacity>
      </View> :
        <View style={{
          flexDirection:
            'row', justifyContent:
            'center'
        }}>
          <TouchableOpacity
            onPress={()=> {

            this.setState({
             loadUrl: "card.html#!/customer-dashboard?userType=Authenticated",
            showWeb:true,

           });

            }}>

            <Image style={{ marginLeft: 20, height: 20, width: 20, resizeMode: "contain" }}
              source={require('../assets/header_icons/icon_arrow_left.png')}
            />

          </TouchableOpacity>
        </View>,
    }
  }

正在抛出this.setState is not an function

请让我知道如何实现这一目标。我们如何从静态navigationOptions

更改状态值

2 个答案:

答案 0 :(得分:0)

您需要使用setParamsgetParams

由于navigationOptions是静态的,因此不能使用this.setState,因此需要在应用中设置参数,并在标头中获取它,反之亦然。

在您的组件中,您将在componentDidMount中拥有类似

componentDidMount(){
    this.props.navigation.setParams({someThing: somethingFromYourComponent });
}

static navigationOptions中,您将看到类似的内容

const someThing = this.props.navigation.getParam('someThing')

现在在您的navigationOptions中,someThing将是somethingFromYourComponent

这样,您可以传递任何内容。功能,组件,对象...

在您的情况下,somethingFromYourComponent可以是更新状态的函数,您可以在标头中将其更改为onPress={() => someThing()}

这在docs

中有解释

您还应该注意

  

React Navigation不保证您的屏幕组件将在标题之前安装。由于递增计数参数是在componentDidMount中设置的,因此我们可能无法在navigationOptions中使用它。这通常不会有问题,因为如果回调为null,则onPress for Button和Touchable组件将不执行任何操作。如果您在此处拥有自己的自定义组件,则应确保其行为符合预期,其新闻处理程序属性为null。

这是文档中的示例,其中他们通过标题中的按钮执行setState(就像您要执行的操作一样)

class HomeScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    return {
      headerTitle: <LogoTitle />,
      headerRight: (
        <Button
          onPress={navigation.getParam('increaseCount')}
          title="+1"
          color="#fff"
        />
      ),
    };
  };

  componentDidMount() {
    this.props.navigation.setParams({ increaseCount: this._increaseCount });
  }

  state = {
    count: 0,
  };

  _increaseCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  /* later in the render function we display the count */
}

答案 1 :(得分:0)

您可以为此使用redux和react hooks。由于不能在类组件中使用钩子,因此我们可以绑定功能组件和类组件。

Dashboard.js

import React, { Component } from "react";
import {
  View,
  Text,
  Image,
  StyleSheet,
  Dimensions,
  TouchableOpacity,
  ScrollView,
  ActivityIndicator
} from "react-native";
import LoginScreen from "./LoginScreen";
import SignUpScreen from "./SignUpScreen";
import { connect, useDispatch } from "react-redux";
import dashboardActions from "../store/actions/dashboard";
import Colors from "../constants/Colors";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/HeaderButton";
import OrientationScreen from "./OrientationScreen";

const openGallery = props => {
   const dispatch = useDispatch();
   return dispatch(dashboardActions.openOrientation());
};
class Dashboard extends Component {
render() {
    const dashboard = this.props;
    if (dashboard.orientation) {
      return <OrientationScreen />;
    } else {
      return (
        <View style={styles.screen}>
          {this.props.dashboard.loading && (
            <View style={styles.loading}>
              <ActivityIndicator color={Colors.blueButton} size="large" />
            </View>
          )}
          <Text>You are logged in</Text>
        </View>
      );
    }
  }
   _openOrientation() {
    openGallery();
  }
  static navigationOptions = ({ navigation, navigationOptions }) => {
    const params = navigation.state.params || {};
    return {
      headerTitle: "Dashboard",
      headerRight: (
        <HeaderButtons HeaderButtonComponent={HeaderButton}>
          <Item
            Title="Orientation"
            iconName="ios-help-circle-outline"
            iconSize={30}
            onPress={params.openOrientation}
          />
          <Item
            Title="Menu"
            iconName="ios-menu"
            iconSize={30}
            onPress={() => navigation.toggleDrawer()}
          />
        </HeaderButtons>
      )
    };
  }
 }
 const mapStateToProps = state => {
  const { auth, dashboard } = state;
  return { auth, dashboard };
};
export default connect(mapStateToProps)(Dashboard);

actions / dashboard.js

const openOrientation = () => {
  return dispatch => {
    return dispatch({
      type: "OPEN_ORIENTATION"
    });
  };
};

export default {
  openOrientation
};

reducers / dashboard.js

const initialState = {
  loading: false,
  error: null,
  orientation: false,
  UserData: null
};

export default (state = initialState, action) => {
  switch (action.type) {
    case "OPEN_ORIENTATION":
      return {
        ...state,
        orientation: true
      };
    case "CLOSE_ORIENTATION":
      return {
        ...state,
        orientation: false
      };
    case "LOADING":
      return {
        ...state,
        error: null,
        loading: true
      };
    default:
      return state;
  }
};

SwiperFlatList.js

import React, { PureComponent } from "react";
import { Text, Dimensions, Image, StyleSheet, View } from "react-native";

import SwiperFlatList from "react-native-swiper-flatlist";

export default class OrientationScreen extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      images: [
        require("../assets/images/SLIDE-1.jpg"),
        require("../assets/images/SLIDE-2.jpg"),
        require("../assets/images/SLIDE-3.jpg"),
        require("../assets/images/SLIDE-4.jpg"),
        require("../assets/images/SLIDE-5.jpg"),
        require("../assets/images/SLIDE-6.jpg"),
        require("../assets/images/SLIDE-7.jpg"),
        require("../assets/images/SLIDE-8.jpg"),
        require("../assets/images/SLIDE-9.jpg"),
        require("../assets/images/SLIDE-10.jpg"),
        require("../assets/images/SLIDE-11.jpg"),
        require("../assets/images/SLIDE-12.jpg"),
        require("../assets/images/SLIDE-13.jpg"),
        require("../assets/images/SLIDE-14.jpg"),
        require("../assets/images/SLIDE-15.jpg"),
        require("../assets/images/SLIDE-16.jpg"),
        require("../assets/images/SLIDE-17.jpg"),
        require("../assets/images/SLIDE-18.jpg"),
        require("../assets/images/SLIDE-19.jpg"),
        require("../assets/images/SLIDE-20.jpg"),
        require("../assets/images/SLIDE-21.jpg"),
        require("../assets/images/SLIDE-22.jpg"),
        require("../assets/images/SLIDE-23.jpg"),
        require("../assets/images/SLIDE-24.jpg"),
        require("../assets/images/SLIDE-25.jpg"),
        require("../assets/images/SLIDE-26.jpg"),
        require("../assets/images/SLIDE-27.jpg"),
        require("../assets/images/SLIDE-28.jpg"),
        require("../assets/images/SLIDE-29.jpg"),
        require("../assets/images/SLIDE-30.jpg"),
        require("../assets/images/SLIDE-31.jpg"),
        require("../assets/images/SLIDE-32.jpg")
      ]
    };
  }
  render() {
    const orientationBody = this.state.images.map((item, i) => {
      return (
        <View key={i} style={styles.child}>
          <Image
            source={item}
            resizeMode="contain"
            style={styles.imageprofile}
          />
        </View>
      );
    });
    return (
      <View style={styles.container}>
        <SwiperFlatList
          index={0}
          removeClippedSubviews={false}
          showPagination={false}
        >
          {orientationBody}
        </SwiperFlatList>
      </View>
    );
  }
}

export const { width, height } = Dimensions.get("window");

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "white"
  },
  child: {
    height: height * 0.8,
    width,
    justifyContent: "center"
  },
  text: {
    fontSize: width * 0.5,
    textAlign: "center"
  },
  imageprofile: {
    width: "100%"
  }
});