繁体   English   中英

我无法将参数传递给 React Native 上的 props 内的函数

[英]I can't pass arguments to a function inside props on React Native

我是 React Native 开发的新手,我很难理解为什么我传递像<TouchableHighlight onPress={props.executeFunction(props.label)}>这样的函数的参数是 SyntheticBaseEvent,而不是道具。标签本身

在 App.js:37 console.log 上,它显示SyntheticBaseEvent {_reactName: 'onClick', _targetInst: null, type: 'click', nativeEvent: PointerEvent, target:

我是否失去了对原始功能的参考?

应用程序.js:

import { StyleSheet, Text, View } from 'react-native';
import React, { Component } from 'react'
import Calculator from './Calculator';
import { LinearGradient } from 'expo-linear-gradient';

const initialState = {

  displayValue: '0',
  clearDisplay: false,
  previousOperation: null,
  operation: null,
  values: [null, null],
  currentPositionOnValues: 0,
  originalValue: 0

}

class App extends Component {
  
  constructor(props) {
    
    super(props);
    
    this.state = { ...initialState }
    this.clear = this.clear.bind(this);
    this.addDigit = this.addDigit.bind(this);

  }

  clear() {
    this.setState({ ...initialState });
  }

  addDigit(digit) {

    console.log(digit)

    if (digit === "." && this.state.displayValue.includes('.')) {

      // Prevent double decimals
      return

    }

    const clearDisplay = this.state.displayValue === '0' || this.state.clearDisplay

    /* 
        Boolean value saying if it's necessary to clear the display
        True if the currentValue display value is 0 or the variable this.state.clearDisplay is set to true
    */

    const currentValue = clearDisplay ? '' : this.state.displayValue

    /* 
        currentValue shows the 'cleared' value or the display value
    */

    const displayValue = currentValue + digit

    this.setState({ displayValue: displayValue, clearDisplay: false })

    if (digit !== '.') {

      const i = this.state.currentPositionOnValues
      const newValue = parseFloat(displayValue)
      const values = [...this.state.values]
      values[i] = newValue
      this.setState({ values: values })

    }

  }

  render() {

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

        <LinearGradient
          colors={['#4b6cb7', '#182848']}
          style={styles.background}
          start={[1, 1]} end={[0, 0]}
        >
        </LinearGradient>
        <Text style={styles.head}>Calculator</Text>
        <Calculator
          addDigit={() => this.addDigit}
          clear={() => this.clear}
          setOperation={() => this.setOperation}
          displayValue = {this.state.displayValue}
        />
      </View>
    );

  }
}

export default App;

计算器.js

import React from 'react';
import { View } from 'react-native';
import Interface from './Interface';  

const Calculator = (props) => {

    return (
        <View>
            <Interface 
                addDigit={props.addDigit} 
                clear={props.clear} 
                displayValue={props.displayValue}
                setOperation={props.setOperation}
            />
        </View>
    );
    
}


export default Calculator;

接口.js

import React from 'react';
import { View, StyleSheet, FlatList, Text } from 'react-native';
import Button from './Button';
import Display from './Display';

const Interface = (props) => {

    return (

        <View style={style.container}>

            <Display value={props.displayValue} />
            <Button label="AC" executeFunction={props.clear} triple />
            <Button label="/" executeFunction={props.setOperation} operation />
            <Button label="7" executeFunction={props.addDigit} />
            <Button label="8" executeFunction={props.addDigit} />
            <Button label="9" executeFunction={props.addDigit} />
            <Button label="*" executeFunction={props.setOperation} operation />
            <Button label="4" executeFunction={props.addDigit} />
            <Button label="5" executeFunction={props.addDigit} />
            <Button label="6" executeFunction={props.addDigit} />
            <Button label="-" executeFunction={props.setOperation} operation />
            <Button label="1" executeFunction={props.addDigit} />
            <Button label="2" executeFunction={props.addDigit} />
            <Button label="3" executeFunction={props.addDigit} />
            <Button label="+" executeFunction={props.setOperation} operation />
            <Button label="0" executeFunction={props.addDigit} double />
            <Button label="." executeFunction={props.addDigit} />
            <Button label="=" executeFunction={props.setOperation} operation />

        </View>

    );

}

const style = StyleSheet.create({

    container: {
        
        width: 400,
        borderRadius: 5,
        overflow: 'hidden',
        position: 'relative',
        justifyContent: 'center',
        flexDirection: 'row',
        flexWrap: 'wrap',
    }

})

export default Interface

按钮.js

import React from "react";
import { View, StyleSheet, Text, TouchableHighlight } from "react-native";

const Button = (props) => {

    let classes = 'button '
    classes += props.operation ? 'operation' : ''
    classes += props.double ? 'double' : ''
    classes += props.triple ? 'triple' : ''

    if (props.operation) {

        return (

            <TouchableHighlight onPress={props.executeFunction(props.label)}>

                <View style={[style.button, style.operation]}>

                    <Text style={style.text}>
                        {props.label}
                    </Text>

                </View>
            </TouchableHighlight>

        )

    } else if (props.double) {

        return (

            <TouchableHighlight onPress={props.executeFunction(props.label)}>
                <View style={[style.button, style.double]}>

                    <Text style={style.text}>
                        {props.label}
                    </Text>


                </View>
            </TouchableHighlight>

        )

    } else if (props.triple) {

        return (

            <TouchableHighlight onPress={props.executeFunction()}>
                <View style={[style.button, style.triple]}>

                    <Text style={style.text}>
                        {props.label}
                    </Text>

                </View>
            </TouchableHighlight>

        )

    } else {

        return (

            <TouchableHighlight onPress={props.executeFunction(props.label)} activeOpacity={0.8}>
                <View style={[style.button]}>


                    <Text style={style.text}>
                        {props.label}
                    </Text>


                </View>
            </TouchableHighlight>

        )

    }
}

const style = StyleSheet.create({

    button: {

        width: 100,
        height: 100,
        fontSize: 30,
        backgroundColor: '#f0f0f0',
        outline: 'none',
        textAlign: 'center',
        justifyContent: 'space-evenly',

        borderColor: '#888',
        borderWidth: 1,
        borderStyle: 'solid',

    },

    double: {

        width: 200,

    },

    triple: {

        width: 300,

    },

    operation: {
        backgroundColor: '#fa8231',
        color: '#FFF',
    },

    text: {
        fontSize: 30,
        textAlign: 'center',
        justifyContent: 'space-evenly',
    }

})

export default Button

怎么了?

目前,您的代码将在组件加载时执行一次props.executeFunction(props.label)

这是因为该函数在评估时立即被调用:

// directly invokes `props.executeFunction` with `props.label` because of brackets `()`
onPress={props.executeFunction(props.label)} 

因为您的函数返回undefined ,所以这就是随后传递给onPress道具的内容。

解决方案是什么?

如果你想传递props.label ,那么你可以通过匿名函数传递:

onPress={() => props.executeFunction(props.label)}

onPress属性会将匿名函数附加到事件中。 触发事件时,将调用该函数,该函数将根据需要调用props.executeFunction传递props.label

SyntheticEvent

onPress函数在调用处理程序时传递一个SyntheticEvent 我们可以通过在匿名函数中记录事件来看到这一点:

onPress={(event) => console.log(event)} // SyntheticEvent

因此,如果您将props.executeFunction作为直接参数传递给onPress道具,则此事件将被传递:

onPress={props.executeFunction} // passes the event as the argument to `props.executeFunction`

例子

调用内联

这会在计算表达式时执行函数(一次)。 undefined返回并传递给onClick ,因此不会添加onClick处理程序。

 function App(props) { function foo(bar) { console.log(bar); } return ( <button onClick={foo("test")}>Test</button> ); } ReactDOM.render( <App />, document.getElementById("react") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="react"></div>

通过匿名函数调用

onClick处理程序传递匿名函数,该函数将在每次点击时执行。

如果您需要将参数传递给函数,这很有用。

 function App(props) { function foo(bar) { console.log(bar); } return ( <button onClick={() => foo("test")}>Test</button> ); } ReactDOM.render( <App />, document.getElementById("react") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="react"></div>

将函数作为参数传递

事件被传递给函数。

如果您需要访问事件,这很有用。

 function App(props) { function foo(bar) { console.log(bar); // this logs the event as the event is passed } return ( <button onClick={foo}>Test</button> ); } ReactDOM.render( <App />, document.getElementById("react-root") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="react-root"></div>

更新了您的代码: https ://snack.expo.dev/qw9iqqVxs

应用程序.JS

import { StyleSheet, Text, View } from 'react-native';
import React, { Component } from 'react';
import Calculator from './Calculator';
import { LinearGradient } from 'expo-linear-gradient';

const initialState = {
  displayValue: 0,
  clearDisplay: false,
  previousOperation: null,
  operation: null,
  values: [null, null],
  currentPositionOnValues: 0,
  originalValue: 0,
};

class App extends Component {
  constructor(props) {
    super(props);

    this.state = { ...initialState };
    this.clear = this.clear.bind(this);
    this.addDigit = this.addDigit.bind(this);
  }

  clear() {
    this.setState({ ...initialState });
  };

  addDigit(digit){
    if (digit === '.' && this.state.displayValue.includes('.')) {
      // Prevent double decimals
      return;
    }

    const clearDisplay =
      this.state.displayValue === '0' || this.state.clearDisplay;

    /* 
        Boolean value saying if it's necessary to clear the display
        True if the currentValue display value is 0 or the variable this.state.clearDisplay is set to true
    */

    const currentValue = clearDisplay ? '' : this.state.displayValue;

    /* 
        currentValue shows the 'cleared' value or the display value
    */

    const displayValue = currentValue + digit;

    this.setState({ displayValue: displayValue, clearDisplay: false })

    if (digit !== '.') {
      const i = this.state.currentPositionOnValues;
      const newValue = parseFloat(displayValue)
      const values = [...this.state.values];
      values[i] = newValue;
      this.setState({ values: values });
    }
  };

  render() {
    return (
      <View style={styles.container}>
        <LinearGradient
          colors={['#4b6cb7', '#182848']}
          style={styles.background}
          start={[1, 1]}
          end={[0, 0]}></LinearGradient>
        <Text style={styles.head}>Calculator</Text>
        <Text style={styles.head}>
          {JSON.stringify(this.state.displayValue)}
        </Text>
        <Calculator
          addDigit={(digit) => {
            this.addDigit(digit);
          }}
          clear={(value) => {
            this.clear(value)
          }}
          setOperation={this.setOperation}
          displayValue={this.state.displayValue}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },

  background: {
    background: 'red',
  },

  triple: {
    width: 300,
  },

  operation: {
    backgroundColor: '#fa8231',
    color: '#FFF',
  },

  text: {
    fontSize: 30,
    textAlign: 'center',
    justifyContent: 'space-evenly',
  },
});

export default App;

按钮.JS

import React from "react";
import { View, StyleSheet, Text, TouchableHighlight } from "react-native";

const Button = ({operation, double, triple, executeFunction, label}) => {

    let classes = 'button '
    classes += operation ? 'operation' : ''
    classes += double ? 'double' : ''
    classes += triple ? 'triple' : ''

    if (operation) {

        return (

            <TouchableHighlight onPress={()=>executeFunction(label)}>

                <View style={[style.button, style.operation]}>

                    <Text style={style.text}>
                        {label}
                    </Text>

                </View>
            </TouchableHighlight>

        )

    } else if (double) {

        return (

            <TouchableHighlight onPress={()=>executeFunction(label)}>
                <View style={[style.button, style.double]}>

                    <Text style={style.text}>
                        {label}
                    </Text>


                </View>
            </TouchableHighlight>

        )

    } else if (triple) {

        return (

            <TouchableHighlight onPress={()=>executeFunction()}>
                <View style={[style.button, style.triple]}>

                    <Text style={style.text}>
                        {label}
                    </Text>

                </View>
            </TouchableHighlight>

        )

    } else {

        return (

            <TouchableHighlight onPress={()=>executeFunction(label)} activeOpacity={0.8}>
                <View style={[style.button]}>


                    <Text style={style.text}>
                        {label}
                    </Text>


                </View>
            </TouchableHighlight>

        )

    }
}

const style = StyleSheet.create({

    button: {

        width: 100,
        height: 100,
        fontSize: 30,
        backgroundColor: '#f0f0f0',
        outline: 'none',
        textAlign: 'center',
        justifyContent: 'space-evenly',

        borderColor: '#888',
        borderWidth: 1,
        borderStyle: 'solid',

    },

    double: {

        width: 200,

    },

    triple: {

        width: 300,

    },

    operation: {
        backgroundColor: '#fa8231',
        color: '#FFF',
    },

    text: {
        fontSize: 30,
        textAlign: 'center',
        justifyContent: 'space-evenly',
    }

})

export default Button

计算器

import React from 'react';
import { View } from 'react-native';
import Interface from './Interface';  

const Calculator = ({addDigit, clear, displayValue, setOperation}) => {

    return (
        <View>
            <Interface 
                addDigit={addDigit}
                clear={clear}
                displayValue={displayValue}
                setOperation={setOperation}
            />
        </View>
    );
    
}


export default Calculator;

接口.JS

import React from 'react';
import { View, StyleSheet, FlatList, Text } from 'react-native';
import Button from './Button';

const Interface = ({clear, addDigit, setOperation}) => {

    return (

        <View style={style.container}>

            <Button label="AC" executeFunction={clear} triple />
            <Button label="/" executeFunction={setOperation} operation />
            <Button label="7" executeFunction={addDigit} />
            <Button label="8" executeFunction={addDigit} />
            <Button label="9" executeFunction={addDigit} />
            <Button label="*" executeFunction={setOperation} operation />
            <Button label="4" executeFunction={addDigit} />
            <Button label="5" executeFunction={addDigit} />
            <Button label="6" executeFunction={addDigit} />
            <Button label="-" executeFunction={setOperation} operation />
            <Button label="1" executeFunction={addDigit} />
            <Button label="2" executeFunction={addDigit} />
            <Button label="3" executeFunction={addDigit} />
            <Button label="+" executeFunction={setOperation} operation />
            <Button label="0" executeFunction={addDigit} double />
            <Button label="." executeFunction={addDigit} />
            <Button label="=" executeFunction={setOperation} operation />

        </View>

    );

}

const style = StyleSheet.create({

    container: {
        
        width: 400,
        borderRadius: 5,
        overflow: 'hidden',
        position: 'relative',
        justifyContent: 'center',
        flexDirection: 'row',
        flexWrap: 'wrap',
    }

})

export default Interface

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM