【问题标题】:Read the value of Parent state and pass Boolean to Child Component React读取 Parent 状态的值并将 Boolean 传递给子组件 React
【发布时间】:2018-06-27 16:47:55
【问题描述】:

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

在我的父组件中,我有一个状态属性 (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
    }));
}

然后在我的子 (Button) 组件中,我想评估 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;

【问题讨论】:

    标签: javascript reactjs react-native


    【解决方案1】:

    按钮上下文中没有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>
    

    【讨论】:

    • 当我这样做时,按钮仍然没有改变。
    • 我希望在每次按下时都更改状态值。也许它没有这样做?
    • props 只是收到一个值。这就是为什么我很困惑。这只是阅读状态。 onPress 正在调用 setState ,这将根据我的理解强制重新渲染。
    • 不要使用setState( prevState =&gt; {audioPlaying: !prevState.audioPlaying } ),试试setState({ audioPlaying : !this.state.audioPlaying })。我在 jsFiddle 中运行了一个测试,这对我产生了影响,尽管我现在不确定为什么。
    • 它仍然不适合我。我在 Button 组件中记录了状态,发现我的“audioPlaying”状态正在从父级传递到子级。但是,我的 onPress 道具并没有像我想象的那样调用该函数。我已经尝试过了,但它仍然没有用。 onPress={() => this.playPauseHandler()}
    【解决方案2】:

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

    两个问题:

    捕捉触摸事件

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

    TouchableOpacity,我正在使用的那个:

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

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

    所有 Touchable 都接受 onPress 属性。因此,通过将 onPress 属性添加到 Touchable,我可以捕获触摸事件,而不仅仅是触发它。

    将回调传递给父级

    这篇文章帮助我更多地了解了如何从子级调用父函数。

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

    所以我在 TouchableOpacity 中调用 playPause()(我重命名了道具并对其进行了解构),它从触摸事件触发,导致状态改变和组件重新渲染。

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

    【讨论】:

    • 很高兴它的工作!我建议您清理代码的一个小改动是&lt;MaterialIcons name={audioPlaying ? 'pause' : 'play-arrow'} size={50} color="#87888C" /&gt;
    • 哦,是的,没错。我正在阅读有关“真实和虚假”的内容,并担心道具本身可能被认为是真实的并让我感到困惑/使其更难调试。
    猜你喜欢
    • 2019-01-20
    • 2022-01-18
    • 2020-07-24
    • 2022-07-15
    • 2019-08-09
    • 1970-01-01
    • 2019-03-08
    • 2019-05-16
    • 2020-07-04
    相关资源
    最近更新 更多