如何在React-Native中重新呈现选项卡

时间:2018-02-17 20:08:01

标签: javascript reactjs react-native

我有一个React-Native闪卡应用程序,它使用两个选项卡,一个Home选项卡和一个New Deck选项卡进行引导。 “主页”选项卡是默认选项卡,您可以按或滑动到“新建套牌”选项卡。

  • “主页”选项卡显示用户当前保存的所有套牌。

  • 在New Deck选项卡上,我让用户输入新牌组的标题并按下提交按钮。按下提交按钮后,我将重新导航到“主页”选项卡。

我的问题是:我在世界上如何通过New Deck选项卡上的按钮按下Home选项卡上的重新渲染,以便用户可以看到他们刚刚创建的套牌? / p>

我知道我可以使用Redux来解决这个问题,但是该应用程序的其他任何部分都没有在" Redux"中进行优化。时尚,我真的不想重新设计我的应用程序的架构,仅用于更新单个屏幕,主要是因为这是我需要此功能的唯一实例。

我试图通过从StackNavigator组件一直传递包含this.forceUpdate方法的screenProp来解决这个问题,但它没有用。我还尝试手动更新App组件的状态以触发重新渲染,但重新渲染从未发生过(尽管状态确实更新了)。

App.js

import React, { Component } from 'react'
import { Text, View } from 'react-native'
import AlphaHome from './Components/Home/AlphaHome'
import AlphaQuiz from './Components/Quiz/AlphaQuiz'
import AlphaNewUdaciDeck from './Components/NewUdaciDeck/AlphaNewUdaciDeck'
import AlphaNewUdaciCard from './Components/NewUdaciCard/AlphaNewUdaciCard'
import AlphaUdaciDeckDetails from './Components/UdaciDeckDetails/AlphaUdaciDeckDetails'
import { TabNavigator, StackNavigator } from 'react-navigation'

const Tabs = TabNavigator({
  Home: {
    screen: AlphaHome,
    navigationOptions: {
      tabBarLabel: 'Home',
    },
  },
  NewDeck: {
    screen: AlphaNewUdaciDeck,
    navigationOptions: {
      tabBarLabel: 'New Deck',
    }
  }
}, {
  navigationOptions: {
    header: null,
  },
  tabBarOptions: {
    activeTintColor: 'white',
    indicatorStyle: {
      backgroundColor: 'white'
    },
    style: {
      height: 50,
      borderBottomColor: 'white',
      backgroundColor: 'deepskyblue',
    }
  },
})

const Stack = StackNavigator({
  Home: {
    screen: Tabs,
  },
  AlphaNewUdaciDeck: {
    screen: AlphaNewUdaciDeck,
    navigationOptions: {
      headerTintColor: 'white',
      headerStyle: {
        backgroundColor: 'deepskyblue'
      }
    }
  },
  AlphaNewUdaciCard: {
    screen: AlphaNewUdaciCard,
    navigationOptions: {
      headerTintColor: 'white',
      headerStyle: {
        backgroundColor: 'deepskyblue'
      }
    }
  },
  AlphaUdaciDeckDetails: {
    screen: AlphaUdaciDeckDetails,
    navigationOptions: {
      headerTintColor: 'white',
      headerStyle: {
        backgroundColor: 'deepskyblue'
      }
    }
  },
})

export default class App extends Component {
  render() {
    return (
      <Stack />
    )
  }
}

Home.js

import React, { Component } from 'react'
import { ScrollView, View, Text, StyleSheet, AsyncStorage, ActivityIndicator } from 'react-native'
import UdaciDeck from '../Reusable/UdaciDeck'
import { getAllData } from '../../utils/AsyncApi'

export default class HomeExistingUser extends Component {
  state = {
    decks: null,
  }
  componentDidMount() {
    let decks = getAllData()
    setTimeout(() => {
      this.setState({
        decks
      })
    }, 1000)
  }
  showDetails = (title, count) => {
    this.props.navigation.navigate('AlphaUdaciDeckDetails', {title, count})
  }
  render() {
    const {decks} = this.state
    return (
      decks
      ? <ScrollView contentContainerStyle={styles.container}>
            {decks.map(s => <UdaciDeck key={s[1].title} name={s[1].title} count={s[1].questions.length} method={this.showDetails} />)}
        </ScrollView>
      : <View style={[styles.container, {flex: 1, justifyContent: 'center'}]}>
          <ActivityIndicator size='large' color='white' />
        </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    minHeight: '100%',
    backgroundColor: 'lightskyblue',
    paddingTop: 20,
    paddingBottom: 20,
    alignItems: 'center',
  },
})

NewDeck.js

import React, { Component } from 'react'
import { View, Text, TextInput, StyleSheet, AsyncStorage, TouchableNativeFeedback, Alert } from 'react-native'
import { addDeck } from '../../utils/AsyncApi'

// BUG: when adding a new deck (if HomeExistingUser is true) view doesn't update. Need to figure out a way to update on tab navigate back

export default class AlphaNewUdaciDeck extends Component {
  state = {
    input: '',
    keys: null,
  }
  componentDidMount() {
    AsyncStorage.getAllKeys()
      .then(keys => this.setState({
        keys
      }))
  }
  handleSubmit = () => {
    const {input, keys} = this.state
    input.search(' ') > 0 || input.length < 1 || keys.filter(s => s === input).length > 0
      ? Alert.alert(`Please enter a valid name (${input.length < 1 || keys.filter(s => s === input).length > 0 ? `you can't save a deck with ${input.length < 1 ? 'no' : 'an already used'} name` : "no spaces"})`)
      : addDeck(input)
    ;if(input.search(' ') < 0 || input.length > 0 || keys.filter(s => s === input).length < 1) {
      this.props.navigation.goBack()
    }
  }
  render() {
    return (
      <View style={[styles.container, styles.containerOne]}>
         <View style={styles.containerTwo}>
            <Text style={styles.text}>Name of the deck</Text>
            <Text style={styles.text}>(Please no spaces)</Text>
            <TextInput
              autoFocus={true}
              onChangeText={(input) => this.setState({
                input
              })}
              selectionColor={'deepskyblue'}
              underlineColorAndroid={'transparent'}
              style={styles.input}
            />
            <TouchableNativeFeedback onPress={this.handleSubmit}>
              <View style={styles.btn}>
                <Text style={styles.btnText}>Save Deck</Text>
              </View>
            </TouchableNativeFeedback>
          </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'lightskyblue',
  },
  containerOne: {
    alignItems: 'center',
  },
  containerTwo: {
    marginTop: 50,
  },
  text: {
    color: 'white',
    fontSize: 20,
  },
  input: {
    backgroundColor: 'white',
    height: 50,
    width: 300,
    marginTop: 15,
    fontSize: 20,
    paddingLeft: 5,
    paddingRight: 5,
    color: 'deepskyblue'
  },
  btn: {
    backgroundColor: 'deepskyblue',
    marginTop: 50,
    padding: 20,
    paddingLeft: 50,
    paddingRight: 50,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 5,
  },
  btnText: {
    color: 'white',
  },
})

1 个答案:

答案 0 :(得分:1)

您应该在https://github.com/pmachowski/react-navigation-is-focused-hoc查看react-navigation-focused-hoc-hoc来解决您提到的具体问题。

您也可以尝试

onNavigationStateChange(prevState, newState) 

How can I tell if the screen is navigated to with ReactNavigation

上有一个示例