【问题标题】:React Native - Defined State not able to be useReact Native - 无法使用定义的状态
【发布时间】:2018-03-12 06:05:21
【问题描述】:

此屏幕是从其他屏幕导航的。当此屏幕打开时,它将从 Webhost 数据库加载一些数据并将它们填充到视图控件中。在 Constructor(State) 中定义的变量很少,但是当程序试图调用ShowAll() 函数(单击显示按钮)以显示带有状态中已定义变量内容的警报消息时,程序会显示此错误。

错误:未定义不是对象(评估“this.state.RecipeName”)

export default class SecondActivity extends Component
{


   static navigationOptions = { title: 'View Details',};


constructor(props) {
   super(props)
     this.state={
       RecipeID : '',
       RecipeName : '',
       RecipeType : '',
       RecipeIngredient : '',
       RecipeStep : ''
     }
}

componentDidMount(){

fetch('https://unsurfaced-cross.000webhostapp.com/getRecipeDetailRN.php', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({

      // Getting the id.
      RecipeID: this.props.navigation.state.params.ListViewClickItemHolder

    })

  }).then((response) => response.json())
        .then((responseJson) => {

          this.setState({

            RecipeID : responseJson[0].RecipeID,
            RecipeName : responseJson[0].RecipeName,
            RecipeType : responseJson[0].RecipeType,
            RecipeIngredient : responseJson[0].RecipeIngredient,
            RecipeStep : responseJson[0].RecipeStep

          })

        }).catch((error) => {
          console.error(error);
        });

  }

  ShowAll(){
    Alert.alert(
     'Alert Title',
     this.state.RecipeName,  // **ERROR COME FROM THIS LINE**
     [
     {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
     {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
     {text: 'OK', onPress: () => console.log('OK Pressed')},
     ],
    { cancelable: false }
  )

}




render()
{

return(
   <View style = { styles.MainContainer }>

    <View style={{flex:1, flexDirection: 'column'}} >

     <Text style={styles.textViewContainer} > {'Recipe ID = ' + this.state.RecipeID} </Text>

     <Text style={styles.textViewContainer} > {'Recipe Name = '} </Text>

     <TextInput
       style={styles.textInput}
       onChangeText={(text) => this.setState({RecipeName: text})}
       value={this.state.RecipeName}
     />

     <Text style={styles.textViewContainer} > {'Recipe Type = '} </Text>



     <Picker
       style={{width: 200}}
       selectedValue={this.state.RecipeType}
       onValueChange={
         (itemValue, itemIndex) => {
           this.setState({RecipeType: itemValue, isLoading:true})
           this.componentDidMount()
           this.forceUpdate()
         }
       }>

                             <Picker.Item label="Vegetarian" value="Vegetarian" />
                             <Picker.Item label="Fast Food" value="Fast Food" />
                             <Picker.Item label="Healthy" value="Healthy" />
                             <Picker.Item label="No-Cook" value="No-Cook" />
                             <Picker.Item label="Make Ahead" value="Make Ahead" />

       </Picker>


     <Text style={styles.textViewContainer} > {'Ingredient = '} </Text>

     <TextInput
       style={styles.textInput}
       onChangeText={(text) => this.setState({RecipeIngredient: text})}
       value={this.state.RecipeIngredient}
     />

     <Text style={styles.textViewContainer} > {'Step = '} </Text>

     <TextInput
       style={styles.textInput}
       onChangeText={(text) => this.setState({RecipeStep: text})}
       value={this.state.RecipeStep}
     />


     <Button
         title="Show"
         onPress={this.ShowAll}
         color="#841584"
     />

    </View>

  </View>
);
}
}

RecipeName 变量已经在 Consturctor(State) 中定义,它也可以被 Views 使用/调用。但是当谈到ShowAll() 函数时,它变成了未定义。

当代码已经存在时,为什么/如何变得未定义?

【问题讨论】:

  • 你试过 onPress={this.ShowAll.bind(this)} 吗?
  • 是的,它的工作,谢谢。
  • 但是通常我像上面的代码那样调用函数并没有出现任何问题,为什么要在这种情况下添加.bind(this)?实际上有什么不同? @firats
  • 如果你使用 ES6 类并且你想在渲染中调用你的函数,React 不再自动绑定。解决此问题的一种方法是在渲染中调用绑定。但这种做法其实并不好。因为函数会在每次渲染时重新分配。因此,有几种方法可以做到这一点。我会在答案中解释。
  • 当然,请做。

标签: javascript android react-native ecmascript-6 react-native-android


【解决方案1】:

渲染中的绑定

onChange={this.handleChange.bind(this)}

如果你使用 ES6 类并且你想在渲染中调用你的函数,React 不再自动绑定。解决此问题的一种方法是在渲染中调用绑定。但这种做法其实并不好。因为函数会在每次渲染时重新分配。所以,有几种方法可以做到这一点。

在渲染中使用箭头函数

这种方法类似于渲染方法中的绑定。您可以通过在渲染中使用箭头函数来避免更改 this 上下文:

onChange={e => this.handleChange(e)}

这是做同样事情的另一种方法,但在渲染中绑定的性能仍然相同。唯一的区别是您没有使用“this”。

在构造函数中绑定

避免在渲染中绑定的一种方法是在构造函数中绑定。

constructor(props) {
  super(props);
  this.handleChange = this.handleChange.bind(this);
}

这是 React 文档中当前推荐的“在您的应用程序中获得更好性能”的方法。您只需绑定一次并在每次按下渲染内的按钮时使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 2021-06-03
    • 1970-01-01
    • 2018-03-31
    • 2022-08-18
    • 2021-12-09
    • 2021-04-27
    相关资源
    最近更新 更多