Javascript 从grand child返回父级中的控制状态
我的最高级别:Javascript 从grand child返回父级中的控制状态,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,我的最高级别: import React from 'react'; import JobList from './JobList'; import RightPanel from './RightPanel'; import JobStore from '../../stores/JobStore'; import LoadJobsScreen from '../../actions/jobs-screen/LoadJobsScreen'; import Modal from '../glo
import React from 'react';
import JobList from './JobList';
import RightPanel from './RightPanel';
import JobStore from '../../stores/JobStore';
import LoadJobsScreen from '../../actions/jobs-screen/LoadJobsScreen';
import Modal from '../global/Modal';
export default class JobScreen extends React.Component {
static contextTypes = {
executeAction: React.PropTypes.func.isRequired
};
componentWillMount() {
this.toggleModal = this.toggleModal.bind(this);
this.state = {open: false}
this.context.executeAction(LoadJobsScreen, this);
}
toggleModal() {
this.setState({
open: !this.state.open
});
console.log(this.state.open);
}
render() {
return (
<div className="jobs-screen">
<div className="col-xs-12 col-sm-10 job-list"><JobList /></div>
<div className="col-xs-12 col-sm-2 panel-container">
<div className="right-panel pull-right"><RightPanel /></div>
</div>
<Modal open={this.state.open} toggleModal={this.toggleModal} />
</div>
);
}
}
从“React”导入React;
从“./作业列表”导入作业列表;
从“/RightPanel”导入RightPanel;
从“../../stores/JobStore”导入JobStore;
从“../../actions/jobs screen/LoadJobsScreen”导入LoadJobsScreen;
从“../global/Modal”导入模态;
导出默认类JobScreen扩展React.Component{
静态上下文类型={
执行操作:需要React.PropTypes.func.isRequired
};
组件willmount(){
this.toggleModal=this.toggleModal.bind(this);
this.state={open:false}
this.context.executeAction(LoadJobsScreen,this);
}
toggleModal(){
这是我的国家({
打开:!this.state.open
});
console.log(this.state.open);
}
render(){
返回(
);
}
}
模式是:
import React from 'react';
class Modal extends React.Component {
constructor() {
super();
}
render() {
let open = this.props.open;
return (
<div className={'modal fade'+(open ? '' : ' hide')} tabindex="-1" role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">{this.props.title}</h4>
</div>
<div className="modal-body">
{this.props.children}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
)
}
}
export default Modal;
从“React”导入React;
类Modal扩展了React.Component{
构造函数(){
超级();
}
render(){
让打开=this.props.open;
返回(
&时代;
{this.props.title}
{this.props.children}
接近
保存更改
)
}
}
导出默认模式;
但我想从更深层次的组件中打开和关闭它(以及稍后向它发送数据):
import React from 'react';
import UrgencyToggle from './UrgencyToggle';
import ApproveButton from './ApproveButton';
import ShippingTable from './ShippingTable';
import DropdownButtonList from '../global/DropdownButtonList';
export default class Job extends React.Component {
constructor(props) {
super(props);
}
setUrgency(urgency) {
actionContext.dispatch('SET_JOB_URGENCY', {
data: urgency
})
};
render() {
return ( <
span className = "name" > < img src = "/images/system-icons/pencil.png"
onClick = {
this.toggleModal
}
width = "13" / > < /span>
)
}
};
从“React”导入React;
从“/UrgencyToggle”导入UrgencyToggle;
从“/ApproveButton”导入ApproveButton;
从“/ShippingTable”导入ShippingTable;
从“../global/DropdownButtonList”导入DropdownButtonList;
导出默认类作业扩展React.Component{
建造师(道具){
超级(道具);
}
紧急(紧急){
actionContext.dispatch('SET\u JOB\u emergency'{
数据:紧迫性
})
};
render(){
报税表(<
span className=“name”>
)
}
};
显然,这不起作用,因为toggleModal在JobScreen中一直处于上升状态。如何从这个深度执行祖父母中的功能?如果您的
作业屏幕
、作业列表
、作业
和模态
组件设计为紧密耦合,即未来不会彼此分离,您可以使用JobScreen
作为存储模态状态的工具,并将树作为回调函数向下传递以更新此状态(我简化了一点,并对缺少的组件做了一些假设):
导出默认类JobScreen扩展React.Component{
建造师(道具){
超级(道具);
this.displayName='JobScreen'
此.state={
莫达洛佩内德:错,
模态:“,
}
}
组件willmount(){
this.context.executeAction(LoadJobsScreen,this);
}
toggleModal(){
这是我的国家({
modalOpened:!this.state.modalOpened
});
}
编辑模式(标题){
这是我的国家({
模式:标题
})
}
render(){
返回(
this.toggleModal()/*与arrow func*/}
editModalTitle={(标题)=>this.editModalTitle(标题)}/>
);
}
}
常量作业列表=(道具)=>{
常量作业=[1,2,3]
返回(
{jobs.map(键=>(
-
))}
);
}
常量作业=(道具)=>{
返回(
{
道具。切换模式(e)
editModalTitle(“新标题”)//这里不是很有效,因为我们更新状态两次而不是一次,但这只是为了示例
}}/>
);
}
我故意没有提到如何以这种方式修改模态子对象,因为这是一种绝对的反模式。因此,您应该明确地看一下这样的东西,它提供了一种方法来管理应用程序的状态,并以“单向数据绑定”的方式从任何您想要更新的地方分派操作。我觉得您试图通过使用
context
作为操作调度器来绕过React内部机制。因此,Redux(或另一个Flux库)将是您在这里的最佳选择。为什么不通过子组件上的道具传递toggleModal
回调?就像这样?:您必须将toggleModal
回调从顶级组件传递到子组件,但是在您的示例中,您根本没有使用作业
组件,这里有一个问题。或者您的作业
组件被用作作业列表
组件的子组件,在这种情况下,您必须将切换模式
传递到树下,即通过作业列表
道具从作业屏幕
组件到作业列表
,通过作业
道具从作业列表
组件到作业
组件。在你的问题中添加你的工作列表
组件的代码,我将发布一个带有详细代码的答案:)我想知道,但这不是有点笨拙吗?肯定有更好的办法吗?
export default class JobScreen extends React.Component {
constructor(props) {
super(props);
this.displayName = 'JobScreen'
this.state = {
modalOpened: false,
modalTitle: "",
}
}
componentWillMount() {
this.context.executeAction(LoadJobsScreen, this);
}
toggleModal() {
this.setState({
modalOpened: !this.state.modalOpened
});
}
editModalTitle(title) {
this.setState({
modalTitle: title
})
}
render() {
return (
<div className="jobs-screen">
<div className="col-xs-12 col-sm-10 job-list">
<JobList
toggleModal={() => this.toggleModal() /* auto binding with arrow func */}
editModalTitle={(title) => this.editModalTitle(title)} />
</div>
<Modal
open={this.state.modalOpened}
title={this.state.modalTitle}/>
</div>
);
}
}
const JobList = (props) => {
const jobs = [1,2,3]
return (
<ul>
{jobs.map(key => (
<li key={key}>
<Job
toggleModal={props.toggleModal}
editModalTitle={props.editModalTitle}/>
</li>
))}
</ul>
);
}
const Job = (props) => {
return (
<span className="name">
<img
src="/images/system-icons/pencil.png"
width="13"
onClick={(e) => {
props.toggleModal(e)
props.editModalTitle("new title") //not very efficient here cause we're updating state twice instead of once, but it's just for the sake of the example
}}/>
</span>
);
}