How to call Screen / Component class method from react-navigation Header

做~自己de王妃 提交于 2019-12-09 13:24:45

问题


I need to call SearchScreen class method from a React Navigation Header.

The Navigator look like this:

  Search: {
    screen: SearchScreen,
    path: 'search/:query',
    navigationOptions: {
      title: 'Search',
      header: {
        right: (
          <MaterialCommunityIcons
            name="filter"
            onPress={() => {
              console.log(this);
            }}
            style={{marginRight: 15, color: 'white'}}
            size={24}
          />
        ),
      },
    }
  }

回答1:


I've made it work by doing:

// declare static navigationOptions in the Component
static navigationOptions = {
  title: 'Title',
  header: ({ state }) => ({
    right: (
      <MaterialCommunityIcons
        name="filter"
        onPress={state.params.handleFilterPress}
        style={{marginRight: 15, color: 'white'}}
        size={24}
      />
    ),
  }),
}

_handleFilterPress() {
  // do something
}


componentDidMount() {
  // set handler method with setParams
  this.props.navigation.setParams({ 
    handleFilterPress: this._handleFilterPress.bind(this) 
  });
}



回答2:


I came across same issue and able to resolve the issue from below links.

class MyScreen extends React.Component {
    static navigationOptions = {
        header: {
            right: <Button title={"Save"} onPress={() => this.saveDetails()} />
        }
    };

    saveDetails() {
        alert('Save Details');
    }

    render() {
        return (
            <View />
        );
    }
}

Source: react-native issues 145

Below is my code

import React, { Component } from "react";
import {
  Container,
  Header,
  Item,
  Input,
  Icon,
  Button,
  Text,
  Left,
  Body,
  Right,
  Content,
  Spinner,
  List,
  ListItem
} from "native-base";
import { View, Image, StyleSheet, Keyboard } from "react-native";
import { connect } from "react-redux";
import {
  onClear,
  onSearchTextChanged,
  searchForProfiles
} from "../../actions/searchActions";

class SearchBar extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <Header searchBar rounded>
        <Button
          iconLeft
          style={{ paddingLeft: 0 }}
          light
          onPress={this.props.onBackPress}
        >
          <Icon style={{ marginLeft: 0, fontSize: 35 }} name="arrow-back" />
        </Button>
        <Item>
          <Icon name="ios-search" />
          <Input
            placeholder="Search"
            onChangeText={this.props.onChangeText}
            value={this.props.searchText}
          />
          <Button small transparent onPress={this.props.onClear}>
            <Icon name="ios-close" />
          </Button>
        </Item>
        <Button transparent onPress={this.props.onSearch}>
          <Text>Search</Text>
        </Button>
      </Header>
    );
  }
}

class SearchWorld extends Component {
  static navigationOptions = ({ navigation }) => ({
    left: null,
    header: () => {
      const { state } = navigation;
      return (
        <SearchBar
          onBackPress={() => navigation.goBack()}
          onChangeText={text => {
            state.params.onChangeText(text);
          }}
          onSearch={state.params.onSearch}
          onClear={state.params.onClear}
          searchText={state.params.searchText}
        />
      );
    }
  });

  onChangeText = text => {
    this.props.navigation.setParams({
      ...this.props.navigation.state,
      searchText: text
    });
    this.props.onSearchTextChanged(text);
  };

  onSearch = () => {
    Keyboard.dismiss();
    const profile = { search: "test" };
    const token = this.props.token;
    this.props.searchForProfiles(token, profile);
  };

  onClear = () => {
    this.props.onClear();
    this.props.navigation.setParams({
      ...this.props.navigation.state,
      searchText: ""
    });
  };

  componentDidMount() {
    this.props.navigation.setParams({
      onChangeText: this.onChangeText,
      onSearch: this.onSearch,
      onClear: this.onClear,
      searchText: this.props.searchText
    });
  }

  render() {
    const { searchResults } = this.props;
    let items = [];
    if(searchResults && searchResults.data && searchResults.data.length > 0) {
      items = [...searchResults.data];
    }
    return this.props.loading ? (
      <Container style={{ alignItems: "center", justifyContent: "center" }}>
        <Spinner color="#FE6320" />
      </Container>
    ) : (
      <Container>
        <Content>
          <List
            style={{}}
            dataArray={items}
            renderRow={item => (
              <ListItem style={{ marginLeft: 0}}>
                <Text style={{paddingLeft: 10}}>{item.password}</Text>
              </ListItem>
            )}
          />
        </Content>
      </Container>
    );
  }
}

const mapStateToProps = state => {
  const { token } = state.user;
  const { searchText, searchResults, error, loading } = state.searchReaducer;

  return {
    token,
    searchText,
    searchResults,
    error,
    loading
  };
};

export default connect(mapStateToProps, {
  onClear,
  onSearchTextChanged,
  searchForProfiles
})(SearchWorld);



回答3:


Hooks solution with FunctionComponent, useState and useEffect

Ref the official docs (https://reactnavigation.org/docs/en/header-buttons.html#header-interaction-with-its-screen-component) it is done by:

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 */
}

However I could not get this to work when working with the hooks api. My state variables were always undefined, but after I thought about how the hooks api is implemented it all made sense, so the solution was to update the navigation param every time a significant state variable was changed:

const [count, setCount] = useState(0);

useEffect(() => {
    props.navigation.setParams({ increaseCount });
}, [count]);

const increaseCount = () => setCount(count + 1);



回答4:


I've resolved the issueI've resolved the issue be the following way:

static navigationOptions = ({ navigation }) => {
    return {
        headerRight: () => (

            <TouchableOpacity
                onPress={navigation.getParam('onPressSyncButton')}>
                <Text>Sync</Text>
            </TouchableOpacity>
        ),
    };
};

componentDidMount() {
    this.props.navigation.setParams({ onPressSyncButton: this._onPressSyncButton });
}

_onPressSyncButton = () => {
     console.log("function called");
}


来源:https://stackoverflow.com/questions/42377301/how-to-call-screen-component-class-method-from-react-navigation-header

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!