【问题标题】:How to call Screen / Component class method from react-navigation Header如何从 react-navigation Header 调用 Screen / Component 类方法
【发布时间】:2017-02-21 20:27:55
【问题描述】:

我需要从 React Navigation Header 调用 SearchScreen 类方法。

导航器如下所示:

  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}
          />
        ),
      },
    }
  }

【问题讨论】:

  • 我添加功能的唯一方法是在按钮或图标组件本身中添加逻辑并使用 redux 操作 - 而不是引用屏幕本身

标签: react-native react-navigation


【解决方案1】:

我已经做到了:

// 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) 
  });
}

【讨论】:

  • @KartiikeyaBaleneni 在 componentWillMount 上尝试 navigation.setParams,它会抛出任何错误吗?
  • 这个模式对我有用,我创建了一个简单的 HOC 来让它更容易实现——npmjs.com/package/react-navigation-underscore
  • 您还在导航器中设置了params,否则它将是未定义的@Kartiikeya
【解决方案2】:

我已经通过以下方式解决了这个问题:

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");
}

【讨论】:

    【解决方案3】:

    使用FunctionComponentuseStateuseEffect 的挂钩解决方案

    参考官方文档 (https://reactnavigation.org/docs/en/header-buttons.html#header-interaction-with-its-screen-component) 由以下人员完成:

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

    但是,在使用 hooks api 时,我无法让它工作。我的状态变量一直是undefined,但是在我考虑了 hooks api 是如何实现的之后,一切都变得有意义了,所以解决方案是每次更改重要的状态变量时更新导航参数:

    const [count, setCount] = useState(0);
    
    useEffect(() => {
        props.navigation.setParams({ increaseCount });
    }, [count]);
    
    const increaseCount = () => setCount(count + 1);
    

    【讨论】:

    • 尝试使用 useEffect 设置参数时出现无限循环。你能分享你的完整代码示例吗?
    • @Jason 我认为如果您在useEffect 函数中有其他状态更改功能,可能会发生这种情况。我修复它的方法是检查它是否需要更新并相应地更新。例如,我有一个 User 对象,该对象已加载到 useEffect 中,并且仅当对象为 undefined 时才加载,然后继续更新 props.navigation.setParams({ increaseCount }); 抱歉延迟,如果您仍然想要,请告诉我我将答案更改为我的特定版本。
    【解决方案4】:

    我遇到了同样的问题,并且能够通过以下链接解决问题。

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

    来源:react-native issues 145

    下面是我的代码

    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);
    

    【讨论】:

      【解决方案5】:
      static navigationOptions =  ({navigation}) => {
      return {
       headerTitle: () => <HeaderTitle />,
       headerRight: () => (<Button iconLeft transparent small onPress = {navigation.getParam('onPressSyncButton')}>
            <Icon style ={{color:'white', fontWeight:'bold'}} name='md-save' size = {32} />
                 <Text style ={{color:'white', fontWeight:'bold'}}>save</Text>
          </Button>),
       headerTintColor:'black',
       headerStyle: {
         backgroundColor: '#6200EE'
       },
      }
      };
      
      this.props.navigation.setParams({ onPressSyncButton: this.updateUserProfile });
      

      【讨论】:

        猜你喜欢
        • 2022-12-27
        • 1970-01-01
        • 1970-01-01
        • 2019-04-07
        • 2021-08-10
        • 2017-09-21
        • 1970-01-01
        • 2018-03-05
        • 2012-01-22
        相关资源
        最近更新 更多