即使绑定了属性,也“无法读取未定义的属性'setState'”

时间:2019-07-16 11:30:55

标签: javascript reactjs jestjs enzyme

我试图测试在组件中的链接上发生单击动作时确实调用了某个函数。我一直收到错误Cannot read property 'setState' of undefined。但是,另一个文件中的此功能已绑定到组件中的构造函数。

组件

import { toggleEditMode } from './otherFile.js'
class PersonalInformation extends Component {
  constructor(props) {
    super(props);
    this.state = {editMode: false}
    this.toggleEditMode = toggleEditMode.bind(this);
  }

  render(){
   const { editMode } = this.state;
   return(
     <div>
{!editMode &&
            <div className="col-md-4 hidden-sm-down">
              <a
                id="editingToggleButton"
                className="display-block"
                role="button"
                href="javascript:void(0);"
                onClick={() => this.toggleEditMode()}
              >
                <span className="icon icon-sm dls-icon-edit" />
                <span className="pad-1-l">Edit</span>
              </a>
            </div>
          }
     </div>
    )
  }
}

toggleEdit方法

export function toggleEditMode() {
  this.setState({ editMode: !this.state.editMode })
}

测试

describe('edit', () => {
  it('should switch to editMode with click', () => {
  const toggleEditMode = jest.fn();
  const wrapper = mount(
    <PersonalInformation
      toggleEditMode={toggleEditMode}
    />
  );
    wrapper.find('#editingToggleButton').simulate('click');
    expect(toggleEditMode).toHaveBeenCalled();
});
}

呈现错误时,它专门指向toggleEdit函数中的this.setState

2 个答案:

答案 0 :(得分:1)

这是问题

您将函数绑定在构造函数中,但将其用作箭头函数。

您应该做的是将绑定添加到箭头函数中,或者仅传递函数引用。

this.toggleEditMode = toggleEditMode.bind(this);
// and 
onClick={this.toggleEditMode}

OR

// remove .bind from the constructor
this.toggleEditMode = toggleEditMode
// and 
onClick={() => this.toggleEditMode.bind(this)}

但是我认为您应该使用第一种情况,因为第二种情况会在每个渲染器上重新创建箭头功能。

答案 1 :(得分:0)

您可以简单地使用reactjs hooks来更改状态

这是演示。

function PersonalInformation() {
  const [editMode, changeEditMode] = useState(false);
  function toggleEditMode() {
    changeEditMode(!editMode);
  }
  return (
    <div>
      <span className="pad-1-l" onClick={toggleEditMode}>
        {!editMode
          ? `Not Editable (click to change)`
          : `editable(click to change)`}
      </span>
    </div>
  );
}

https://codesandbox.io/embed/determined-benz-c5km7