我想从一个组件到另一个组件调用一个函数。谷歌搜索后,我尝试了一些不同的事情,但是由于我是Reactjs的新手,所以我似乎无法解决问题。我以为可以导入状态,然后从其他组件中更改状态(请参见下文),但是我认为自己在树错了树皮?
我想从locationform.js调用header.js中的showMenu()
header.js
import React, { Component, PropTypes } from 'react';
import ReactF1 from 'react-f1';
// Styles.
import styles from './Header.css';
// Elements.
import Menu from './elements/Menu';
// Menu states.
import { states, SHOWBUTTON, IDLE, HIDE, OUT } from './elements/Menu/states';
import transitions from './elements/Menu/transitions';
function changeOffset() {
document.querySelector('svg path').style.strokeDashoffset = 0;
setTimeout("document.querySelector('svg path').style.strokeDashoffset = 171", 2000);
}
export default class Header extends Component {
static get propTypes() {
return {
children: PropTypes.element,
};
}
constructor(props, context) {
super(props, context);
this.state = {
menuState: OUT,
hamburgerState: OUT,
};
}
componentDidMount() {
if (this.props.router.location.pathname === '/') {
setTimeout(() => this.setState({ hamburgerState: SHOWBUTTON }), 6000);
} else {
this.setState({ hamburgerState: SHOWBUTTON });
}
// setTimeout(changeOffset, 8000);
}
completeF1Handler() {}
showMenu() {
this.setState({ menuState: IDLE });
}
hideMenu() {
this.setState({ menuState: HIDE });
}
reset() {
this.setState({ menuState: OUT });
}
render() {
const { stageWidth, stageHeight } = this.props;
return (
<ReactF1
className={styles.Header}
go={this.state.hamburgerState}
states={states(stageWidth, stageHeight)}
transitions={transitions()}
onComplete={() => this.completeF1Handler()}
>
<svg className={styles.hamburger} data-f1="hamburger" width="50" height="50">
<path
className={styles.triangle}
d="M0 0 L50 0 L0 50 Z"
onClick={this.showMenu.bind(this)}
fill={this.props.menuColor}
/>
</svg>
<Menu
go={this.state.menuState}
close={this.hideMenu.bind(this)}
reset={this.reset.bind(this)}
/>
</ReactF1>
);
}
}
locationform.js
import React, { Component, PropTypes } from 'react';
import { isDesktop } from '../../utils/device';
import LocateSelect from '../LocateSelect';
import styles from './LocationForm.css';
import buttonStyles from '../Button/Button.css';
// Menu states.
import { states, SHOWBUTTON, IDLE, HIDE, OUT } from '../Header/elements/Menu/states';
export default class LocationForm extends Component {
static get propTypes() {
return {
zipCode: PropTypes.string,
searchRadius: PropTypes.string,
businessType: PropTypes.string,
handleChange: PropTypes.func,
handleGeolocate: PropTypes.func,
handleSubmit: PropTypes.func,
};
}
constructor(props, context) {
super(props, context);
}
showMenu() {
console.log("show menu");
this.setState({ menuState: IDLE });
}
renderSelect() {
const { searchRadius, businessType, handleChange } = this.props;
return (
<div className={styles.selectContainer}>
<LocateSelect
id="searchRadius"
defaultValue=""
value={searchRadius}
handleChange={handleChange}
options={[
{
value: '',
text: 'SEARCH RADIUS',
},
{
value: '1',
text: '1 MI',
},
{
value: '5',
text: '5 MI',
},
{
value: '10',
text: '10 MI',
},
{
value: '25',
text: '25 MI',
},
]}
/>
<LocateSelect
id="businessType"
defaultValue=""
value={businessType}
handleChange={handleChange}
options={[
{
value: '',
text: 'BUSINESS TYPE',
},
{
value: 'bar',
text: 'Bar',
},
{
value: 'restaurant',
text: 'Restaurant',
},
{
value: 'liquorstore',
text: 'Liquor Store',
},
]}
/>
</div>
);
}
render() {
const {
zipCode,
handleChange,
handleSubmit,
handleGeolocate,
handleFocus,
handleBlur,
} = this.props;
return (
<form className={styles.LocationForm} onSubmit={handleSubmit}>
<input
type="button"
className={`${buttonStyles.Button} ${buttonStyles.dark} ${styles.geolocate}`}
value="Use Current Location"
onClick={handleGeolocate}
/>
<p>OR</p>
<input
id="zipCode"
type="text"
placeholder="ZIP CODE"
value={zipCode}
maxLength="5"
pattern="[0-9]*"
onFocus={handleFocus}
onBlur={handleBlur}
onChange={event => handleChange(event.target.id, event.target.value)}
/>
{this.renderSelect()}
<input
className={`${buttonStyles.Button} ${buttonStyles.dark}`}
type="submit"
value="search"
/>
<div className={buttonStyles.Button} onClick={() => this.showMenu()}>
No
</div>
</form>
);
}
}
答案 0 :(得分:4)
在考虑父子通讯时,您必须为这两个文件编写父文件,并将函数和状态作为prop传递。
例如:
app.js
import Header from './header.js'
import LocationForm from './location-form.js'
export default class App extends Component {
state = {menuState : 'out'}
showMenu() {
this.setState({ menuState:'idle' });
}
render(){
return(
<div>
<Header showMenu={this.showMenu} menuState={this.state.menuState}/>
<LocationForm showMenu={this.showMenu} menuState={this.state.menuState}/>
</div>
)
}
}
我认为这种思想观念将帮助您找到答案
答案 1 :(得分:0)
因此,在反应中,为了将数据从父元素传递到子元素,您需要将它们作为道具向下传递
因此,以您的Menu组件为例,您可以像这样将要使用的方法传递给该子组件:(我建议将它们转换为es6语法,这样就不必费心绑定了)。
//METHODS SECTION
const showMenu = () => {
this.setState({ menuState: IDLE });
}
const hideMenu = () => {
this.setState({ menuState: HIDE });
}
const reset = () => {
this.setState({ menuState: OUT });
}
//IN YOUR RENDER METHOD
<Menu
go={this.state.menuState}
close={this.hideMenu.bind(this)}
reset={this.reset.bind(this)}
showMenu={this.showMenu}
hideMenu={this.hideMenu}
reset={this.reset}
/>
然后在子组件中,将该方法称为this.props.showMenu或this.props.hideMenu或this.props.reset:
onClick(() => {this.props.showMenu()})
如果您希望该方法在事件上触发,则应像上面一样将其包装在一个匿名函数中。您还可以将其添加到子组件中的另一个方法中,该子方法在调用时将被调用,这样:
const doSomething = () => {
count++
this.props.showMenu()
}
onClick(() => {this.doSomething()})
在子组件中使用该方法时,它仍然绑定到父组件。这是将数据发送回父级的主要方法。例如,您可以让该方法简单地在父组件上设置一个值的setState,将该方法作为具有参数要求的道具传递给子对象,在子对象上传递参数,并在调用它时将其发送回父对象。 。 (让我知道这是否令人困惑)
您的应用中有很多不是非常“ React”的内容,因此,我绝对建议您仔细阅读其文档。从https://reactjs.org/docs/components-and-props.html开始,并在YouTube上观看一些有关React中状态管理的视频。
答案 2 :(得分:0)
父母之间的交流最好被认为具有两种操作方法:
这意味着组件之间的关系是通过定义的。他们的道具。这是一种通讯方式,可以更轻松地将组件构建为在特定上下文中可以连接的独立模块。
所以,如果您有类似的东西:
Child A
/
Parent
\
Child B
然后,您需要通过进行通信。 Parent
。子代将调用其父代提供给他们的函数,父代会将新的prop传递给子代组件。
您还可以通过context
来执行此操作,这样可以避免必须手动传递所有这些道具,但不会影响组件可用的通信流。
const ButtonComponent = (props) => {
return (
<div>
Child
<button onClick={props.handleClick}>
Do the thing
</button>
</div>
);
};
const CountDisplay = (props) => {
return (
<div>{props.count}</div>
);
};
const Parent = (props) => {
const parentLog = () => console.log('log from parent');
const [
currentCount,
setCurrentCount,
] = React.useState(0);
return (
<div>
Parent
<ButtonComponent handleClick={() => setCurrentCount(currentCount + 1)} />
<CountDisplay count={currentCount} />
</div>
);
};
ReactDOM.render(<Parent />, document.getElementById('app'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="app"></div>