读取父状态的值并将布尔值传递给子组件React

时间:2018-06-27 16:47:56

标签: javascript reactjs react-native

我在学习如何在React Native中在父子之间传递数据时遇到了麻烦。

在我的父组件中,我有一个state属性(audioPlaying),它是一个布尔值。

state = {
    //The title informs the Button and TitleArea components
    title: 'hello',
    audioPlaying: false,
};

我想通过按一个按钮(onPress)来更改该值。

<Button
    title={this.state.title}
    onPress={this.playPauseHandler}
    audioPlaying={this.state.audioPlaying}
/>

...通过调用playPauseHandler。

playPauseHandler = () => {
    this.setState(prevState => ({
        audioPlaying: !prevState.audioPlaying
    }));
}

然后在我的孩子(按钮)组件中,我想评估audioPlaying状态属性。如果是真的,我想展示一件事,而假的我想展示另一件事。

<View style={styles.playBtnStyle}>
    {this.props.audioPlaying === false ? (
        <MaterialIcons
            name='play-arrow'
            size={50}
            color="#87888C"
        />
        ) : (
        <MaterialIcons
            name='pause'
            size={50}
            color="#87888C"
        />
        )}
    }
</View>

但是,当我运行它时,我无法获得audioPlaying的值。 React Native Error Message

这是这两个文件的完整文件:

App.js

import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';

import Carousel from './src/components/Carousel/Carousel';
import Button from './src/components/Button/Button';
import TitleArea from './src/components/TitleArea/TitleArea';
import MapArea from './src/components/MapArea/MapArea';

const styles = {
	container: {
		flex: 1,
		justifyContent: 'space-between',
	},
	playArea: {
		flex: 1,
	},
};

export default class App extends Component {
	state = {
		//The title informs the Button and TitleArea components
		title: 'hello',
		audioPlaying: false,
	};

	playPauseHandler = () => {
		this.setState(prevState => ({
			audioPlaying: !prevState.audioPlaying
		}));
	}

	render() {
		return (
			<View style={styles.container}>
				<TitleArea title={this.state.title} />
				<StatusBar hidden={false} />
				<Carousel />
				<MapArea />
				<Button
					title={this.state.title}
					onPress={this.playPauseHandler}
					audioPlaying={this.state.audioPlaying}
				/>
			</View>
		);
	}
}

Button.js

import React, { Component } from 'react';
import { Text, View, TouchableOpacity, Dimensions } from 'react-native';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';

const { width } = Dimensions.get('window');
const height = width * 0.2;
const styles = {
	textStyle: {
		color: '#87888C',
		fontSize: 18,
		fontWeight: '600',
		backgroundColor: 'white',
		alignSelf: 'center',
	},
	buttonContainer: {
		height,
		flexDirection: 'row',
		backgroundColor: 'white',
		alignItems: 'center',
	},
	playBtnStyle: {
		marginLeft: 50,
		backgroundColor: 'white',
	},
	childStyle: {
		flex: 1,
	},
};

const button = (props) => {
	return (
		<View style={styles.buttonContainer}>
			<TouchableOpacity>
				<View style={styles.playBtnStyle}>
					{this.props.audioPlaying === false ? (
						<MaterialIcons
							name='play-arrow'
							size={50}
							color="#87888C"
						/>
					 ) : (
						<MaterialIcons
							name='pause'
							size={50}
							color="#87888C"
						/>
					 )}
					}
				</View>
			</TouchableOpacity>

			<View style={styles.childStyle}>
				<Text style={styles.textStyle}>Chapter 1: {props.title}</Text>
			</View>
		</View>
	);
}

export default button;

2 个答案:

答案 0 :(得分:4)

按钮上下文中没有this。那只是一个返回JSX的函数。 而是使用props

<View style={styles.playBtnStyle}>
  {props.audioPlaying === false ? (
    <MaterialIcons
      name='play-arrow'
      size={50}
      color="#87888C"
    />
  ) : (
    <MaterialIcons
      name='pause'
      size={50}
      color="#87888C"
    />
  )}
</View>

答案 1 :(得分:0)

好,所以我解决了我自己的问题! (成为开发人员的第一步)

两个问题:

捕获触摸事件

React Native具有所谓的Touchables。根据文档,这些是“使视图正确响应触摸的包装器”。

TouchableOpacity,我正在使用的那个

  

按下时,已包装视图的不透明度降低,从而使其变暗。不透明度是通过将子级包装在Animated.View中控制的,该视图已添加到视图层次结构中。

https://facebook.github.io/react-native/docs/touchablewithoutfeedback#onpress

所有可触摸对象均接受onPress道具。因此,通过将onPress道具添加到Touchable中,我可以捕获触摸事件,而不仅仅是触发它。

将回调传递给家长

本文帮助我更多地了解了如何从孩子那里调用父函数。

https://medium.com/@thejasonfile/callback-functions-in-react-e822ebede766

因此,我在TouchableOpacity中调用playPause()(我重命名了prop并对其进行了结构分解),该事件从触摸事件触发,导致状态改变和组件重新呈现。

const button = (props) => {
  const {
    title,
    audioPlaying,
    playPause,
  } = props;
  return (
        <View style={styles.buttonContainer}>
            <TouchableOpacity onPress={() => playPause()}>
                <View style={styles.playBtnStyle}>
                    {audioPlaying === false ? (
                        <MaterialIcons
                            name='play-arrow'
                            size={50}
                            color="#87888C"
                        />
                    ) : (
                            <MaterialIcons
                                name='pause'
                                size={50}
                                color="#87888C"
                            />
                    )
                    }
                </View>
            </TouchableOpacity>
            <View style={styles.childStyle}>
                <Text style={styles.textStyle}>
                  Chapter 1:
                    {title}
                </Text>
            </View>
        </View>
  );
};