简体   繁体   English

通过 function 作为 Reactjs 中的道具

[英]Passing function as props in Reactjs

I am trying to pass function as prop.我试图通过 function 作为道具。 I did this before but now with the same logic it is giving me error (this.props.functionName is not a function).我以前这样做过,但现在使用相同的逻辑它给了我错误(this.props.functionName 不是函数)。 I have a child (Navbar) and a parent component(MainComponent).我有一个孩子(导航栏)和一个父组件(MainComponent)。 I want to send a input value from Navbar to MainComponet and set it to the state value in parent Component.我想将输入值从导航栏发送到 MainComponet,并将其设置为父组件中的 state 值。

Parent Component父组件

    import React ,{Component}from 'react'
    import Navbar from '../Presentational/Navbar'

class Main extends Component{
constructor(props){
    super(props)
    this.state = {
        searchItem: ''
    }
}

GetSearchItem(search){
    this.setState({searchItem:search})
}
render(){
    return(
        <div className = 'container'>
            <div className = 'row'>
                <div className = 'col-12 mt-1'>
                    <Navbar onChange = {(search)=>this.GetSearchItem(search)}></Navbar>
                </div>
            </div>
            <div className = 'row'>
                <div className = 'col-3'>
                    <h3>{this.state.searchItem}</h3>
                </div>
            </div>
        </div>
    )
}
}

export default Main

Child Component (Navbar)子组件(导航栏)

import React,{Component} from 'react'
import {AppBar,Toolbar,IconButton,Typography,InputBase} from '@material-ui/core'
import MenuIcon from '@material-ui/icons/Menu';
import SearchIcon from '@material-ui/icons/Search';
import {fade , makeStyles} from '@material-ui/core/styles'

const useStyles = makeStyles((theme) => ({
root: {
  flexGrow: 1,
},
menuButton: {
  marginRight: theme.spacing(2),
},
title: {
  flexGrow: 1,
  display: 'none',
  [theme.breakpoints.up('sm')]: {
    display: 'block',
  },
},
search: {
  position: 'relative',
  borderRadius: theme.shape.borderRadius,
  backgroundColor: fade(theme.palette.common.white, 0.15),
  '&:hover': {
    backgroundColor: fade(theme.palette.common.white, 0.25),
  },
  marginLeft: 0,
  width: '100%',
  [theme.breakpoints.up('sm')]: {
    marginLeft: theme.spacing(1),
    width: 'auto',
  },
},
searchIcon: {
  padding: theme.spacing(0, 2),
  height: '100%',
  position: 'absolute',
  pointerEvents: 'none',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
},
inputRoot: {
  color: 'inherit',
},
inputInput: {
  padding: theme.spacing(1, 1, 1, 0),
  // vertical padding + font size from searchIcon
  paddingLeft: `calc(1em + ${theme.spacing(4)}px)`,
  transition: theme.transitions.create('width'),
  width: '100%',
  [theme.breakpoints.up('sm')]: {
    width: '12ch',
    '&:focus': {
      width: '20ch',
    },
  },
},
 }));

class Navbar extends Component{

render(){
    const classes  = this.props.classes;;
    return(
        <div className={classes.root}>
            <AppBar position="static">
                <Toolbar>
                    <IconButton
                        edge="start"
                        className={classes.menuButton}
                        color="inherit"
                        aria-label="open drawer"
                    >
                        <MenuIcon />
                    </IconButton>
                    <Typography className={classes.title} variant="h6" noWrap>
                        Pizaa Valley
                    </Typography>
                    <div className={classes.search}>
                        <div className={classes.searchIcon}>
                        <SearchIcon />
                        </div>
                        <InputBase
                        placeholder="Search…"
                        classes={{
                            root: classes.inputRoot,
                            input: classes.inputInput,
                        }}
                        inputProps={{ 'aria-label': 'search' }}
                        onChange={(event)=>this.props.onChange(event.target.value)}
                        />
                    </div>
                </Toolbar>
            </AppBar>
        </div>
    )
}
}


export default () => {
const classes = useStyles();
return (
    <Navbar classes={classes} />
)
}

The problem is that you have two Navbar types.问题是您有两种Navbar类型。 You first have the class component created using class Navbar .您首先拥有使用class Navbar创建的 class 组件。 And second you have the following functional component defined here:其次,您在此处定义了以下功能组件:

export default () => {
const classes = useStyles();
return (
    <Navbar classes={classes} />
)
}

When you do当你这样做

import Navbar from '../Presentational/Navbar'

<Navbar onChange = {(search)=>this.GetSearchItem(search)}></Navbar>

The onChange prop is correctly given to the functional component, but is never passed along to the class-based component. onChange正确地提供给功能组件,但永远不会传递给基于类的组件。 You can fix this by replacing your functional component with the below code:您可以通过使用以下代码替换您的功能组件来解决此问题:

export default props => {
    const classes = useStyles();
    return (
        // using the "spread operator", we pass along all the props given
        // to the functional component, so the class-based component can 
        // also access these
        <Navbar {...props} classes={classes} />
    )
}

you've done everything correctly except change this:你已经正确地完成了所有的事情,除了改变这个:

GetSearchItem(search){
    this.setState({searchItem:search})
}

to

GetSearchItem = (search) => {
    this.setState({searchItem:search})
}

as an arrow function it has access to the scope above如箭头 function 它可以访问上面的 scope

Try with the following:-尝试以下方法:-

In your parent component modified the below line:-在您的父组件中修改了以下行:-

  <Navbar onChangeCallBack = {(search)=>this.GetSearchItem(search)}></Navbar>

In your child Navbar component only modified the below line:-在您的子导航栏组件中,仅修改了以下行:-

  onChange={(event)=>this.props.onChangeCallBack(event.target.value)}

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

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