冲突'this'引用了子组件和父组件

时间:2017-09-09 14:17:43

标签: reactjs

我还在代码块中提到了问题作为注释,我有一个子组件(Comments)包含表单元素,当它提交时我调用“SaveComment()”方法的父组件,但是这会导致“this”冲突参考..

class VideoDetail extends Component{
  constructor(props){
    super(props)
    this.appState=this.props.appState
    debugger//here this.appState is correctly defined
  }
    SaveComment(e){
      e.preventDefault();
      this.appState.comment.name = this.name.value;
      //this.appState is undefined since "this" keywords refers to 'Comments' child component 
      //How can I both use my parent "this" object and a reference object that can get values form child component like here;"this.name.value"
    }
    render(){
        return(
        <div className="show-top-grids">
            <Comments {...{totalCommentCount:"12345",bok:"boook!", SaveComment:this.SaveComment}}/>
      </div>
        )
    }
}

const Comments = (commentContext)=>{
  return (
        <form onSubmit={(e)=>{commentContext.SaveComment(e)}}>
          <input type="text" ref={(input)=>{this.name=input}} placeholder="Name" required=" " />                                           
          <input type="submit" defaultValue="SEND" />
          <div className="clearfix"> </div>
        </form>
  )
}

我该如何解决它或改变我的处理方式?

2 个答案:

答案 0 :(得分:3)

上述代码段需要解决两件事:

  1. 如何确保this引用事件回调中的父实例
  2. 如何将表单值从子级传递给父级。
  3. 要“锁定”this关键字,handling events建议:a)使用property initializer syntax 在构造函数b)中绑定此关键字,这样就不会丢失“this”的上下文”

    要将表单值传递给父级,您只需更改SaveComment(e) - &gt;的参数即可。 SaveComment(comment)中的<VideoDetail /><Comment />中的onSubmit={(e)=>{commentContext.SaveComment(e)}更改onSubmit={(e)=>{commentContext.SaveComment(this.name)} - &gt; props

    总之,React包含单向数据流,父级(state, props) => UI传递给子级,子级需要public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment setHasOptionsMenu(true); View view = inflater.inflate(R.layout.fragment_search, container, false); final SearchBookFragment searchbook=new SearchBookFragment(); final SearchPeopleFragment searchpeople=new SearchPeopleFragment(); TabLayout searchTabLayout = (TabLayout)view.findViewById(R.id.searchTabLayout); searchTabLayout.addTab(searchTabLayout.newTab().setText("book")); searchTabLayout.addTab(searchTabLayout.newTab().setText("person")); searchTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { Toast.makeText(getActivity(),"selecteeeed",Toast.LENGTH_LONG).show(); switch(tab.getPosition()){ case 0: Toast.makeText(getActivity(),"boooook",Toast.LENGTH_LONG).show(); break; case 1: Toast.makeText(getActivity(),"peoppllllle",Toast.LENGTH_LONG).show(); break; } } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); return view; } 进行渲染。如果孩子想要发回信息,通常是通过将参数传递给父母的回调来完成的,这样数据仍然可以单向流动,从而在父母与子女之间实现良好的分离。关于数据的孩子。

答案 1 :(得分:2)

我希望在执行ref={(input)=>{this.name=input}}时,您会在控制台上出错。

要访问州或道具,您需要有权访问其上下文。因此,当声明您的函数时,您必须绑定。最简单的方法是使用arrow函数。因此,在VideoDetail SaveComment SaveComment = (e) => { e.preventDefault(); // your other logic } 看起来像

ref

由于无法在函数组件中使用Comments,因此可以将React.Component函数组件转换为扩展Comments的类。这样你就可以设置ref。如果您希望遵循此路径,则class Comments extends Component { render() { return ( <form onSubmit={(e)=>{this.props.SaveComment(e)}}> <input type="text" ref={(input)=>{this.name=input}} placeholder="Name" required=" " /> <input type="submit" defaultValue="SEND" /> <div className="clearfix"> </div> </form>); } } 看起来像

VideoDetail

在上述访问Comments中的表单值的方法中,您可以传递Comments中的数据。因此,您的class Comments extends Component { onSubmit = (e) => { e.preventDefault(); const formData = { name: this.name.value, }; this.props.SaveComment(formData); } render() { return ( <form onSubmit={this.onSubmit}> <input type="text" ref={(input)=>{this.name=input}} placeholder="Name" required=" " /> <input type="submit" defaultValue="SEND" /> <div className="clearfix"> </div> </form>); } } 组件看起来像

SaveComment

通过上述方式,您可以在formData中添加所需数量的数据并将其发送回父级。而VideoDetail中的 SaveComment = (formData) => { // use formData as you wish } 将转换为

PhysicalNamingStrategy