将setState()绑定到全局函数仅影响组件的一个实例

时间:2019-07-10 13:17:59

标签: javascript reactjs

注意:根据Nicholas Tower的回答,我在做出更改后对问题进行了编辑。

我有一个绑定到组件并更改其状态的全局函数。 我想构建一个表单生成器系统。有一个名为setLabel的全局函数,该函数绑定到名为InputBox的组件并更改其状态。此全局函数由另一个名为ModalPanel的组件触发,该组件控制绑定的组件InputBox上的可编辑属性。为了简化这个问题,我简化了函数和组件类。

这是全局函数:

function setLabel(postID, attributeName ){

    var text = 'example';
    if(text !== ''){

        this.setState({ [attributeName] : text});

    }
}

这是绑定到setLabel函数的组件。注意如何将setLabel函数作为属性从父InputBox组件传递给子ModalPanel组件函数。

class InputBox extends Component{

    constructor(props){
        super(props);
        this.state = {
            placeholder : '',
            maxlength: '',
            type: '',
        }

        this.setLabel = setLabel.bind(this); // Binding this to the global function.
    }

    render(){

        let elementId = "inputElement-" + this.props.idCounter;
        let mainElement = <Form.Control
                              id = {elementId}
                              type = {this.state.type}
                              placeholder = {this.state.placeholder} 
                              maxLength = {this.state.maxlength}
                          />
        return  <Row>
                    <ModalPanel
                        handleHide = {this.props.handleHide}
                        handleShow = {this.props.handleShow}
                        setLabel = {this.setLabel}
                    /> 
                </Row>
    }
}

最后,下面是ModalPanel组件函数,其中触发了setLabel函数。

function ModalPanel(props){

    return(
        ......................
        ......................
        ......................
        <Button variant="primary" onClick = {() => props.setLabel()}>Save changes</Button>
        ......................
        ......................
        ......................)
}
setLabel组件中单击按钮时,必须触发旨在设置InputBox状态的

ModalPanel函数。问题是,窗口上有多个呈现的<InputBox />组件,当我尝试使用此功能时,“状态更改”仅影响<InputBox />组件的第一个实例。我想做的是,每个实例都应该有自己的内部状态,setLabel()函数应该绑定到调用它的特定组件。因此,该功能可以设置不同组件实例的状态。我该怎么办?

添加:

请检查下面的链接,以查看gif图片,显示我的系统工作方式错误。如您所见,即使我选择了第三个输入框元素来编辑其属性(在本例中,将其设置为占位符文本),对第一个输入框也进行了更改。

Go to gif

5 个答案:

答案 0 :(得分:3)

在开头添加this.,如下所示:

this.setLabel = setLabel.bind(this); 

现在,您要在InputBox实例上设置属性。稍后在组件中引用它时,请确保使用this.setLabel对其进行引用。

答案 1 :(得分:0)

setLabel是否在执行特定的postID?是每个<Button />中的<ModalPanel />都作用于同一postID的问题吗?因为您没有在setLabel内部正确使用<ModalPanel />setLabel接受2个参数,现在您的实现未使用任何参数。这是您的点击处理程序。

onClick = {() => props.setLabel()}

尝试console.log内的setLabel并查看单击每个按钮时得到的值

function setLabel(postID, attributeName){
    console.log(postID, attributeName)
    var text = 'example';
    if(text !== ''){

    this.setState({ [attributeName] : text});

    }
}

答案 2 :(得分:0)

由于React组件仅通过props或状态更改进行更新,因此您需要将全局状态与本地状态配对以更新组件。在沙盒环境中,请参见下面的代码。

let value = 0;

function updateStuff () {
  console.log("this from update", this.name);
  value++;
  this.setState({name: "Hakan " + value});
}

class Test extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      name: 'notchanged',
      counter: 1
    }
    this.localFunc = this.localFunc.bind(this)
    updateStuff = updateStuff.bind(this)
  }
  localFunc(){
    let {counter} = this.state;
    this.setState({counter: counter + 1});
    updateStuff();
  }
  render () {
    return (
      <div>
        <div>Test 2</div>; 
        <div>Counter: {this.state.counter}</div>
        <div>Name: {this.state.name}</div> 
        <button onClick={this.localFunc}>Increment</button>
      </div>
    );
  }
}

ReactDOM.render(
  <Test/>,
  document.getElementById('root')
);

答案 3 :(得分:0)

认为,您使用React的方式不正确

对我来说首选方式如下:

  1. 具有一个愚蠢/具有代表性的InputBox,它接受label作为属性(在道具中,不在状态中)
  2. 具有一个智能/容器组件,其中包含多个InputBox的状态并将正确的标签传递到InputBox中
  3. 如果您尝试将InputBox PropertyEditor实现为单独的组件,请考虑添加事件总线,例如通过React Context在事件总线之间共享(甚至使用完整的flux / redux概念)

答案 4 :(得分:-1)

在绑定它们或使用箭头函数后,将其添加到您的函数调用中!