Javascript onBlur/onClick与React中的CodeMirror2冲突
我已经创建了多个代码镜像单元。OnBlur工作正常,但是如果我在另一个单元格上单击Javascript onBlur/onClick与React中的CodeMirror2冲突,javascript,reactjs,onclick,codemirror,onblur,Javascript,Reactjs,Onclick,Codemirror,Onblur,我已经创建了多个代码镜像单元。OnBlur工作正常,但是如果我在另一个单元格上单击run按钮,而不是触发run,它实际上会触发OnBlur,然后我需要再次单击鼠标来触发run。理想情况下,这两个事件都应该在单击“运行”按钮时触发 我已经看到,问题在于这两个事件的优先顺序,建议的解决方案之一是向代码镜像添加ref属性,如ref={cell=>this.cell=cell},然后在与run按钮dothis.cell.focus()相关的另一个处理程序中添加 不幸的是,我甚至无法访问CodeMirro
run
按钮,而不是触发run,它实际上会触发OnBlur,然后我需要再次单击鼠标来触发run。理想情况下,这两个事件都应该在单击“运行”按钮时触发
我已经看到,问题在于这两个事件的优先顺序,建议的解决方案之一是向代码镜像添加ref
属性,如ref={cell=>this.cell=cell}
,然后在与run按钮dothis.cell.focus()
相关的另一个处理程序中添加
不幸的是,我甚至无法访问CodeMirror2的ref
属性,因此无法测试它。我将粘贴这两个组件,任何建议都将不胜感激
总而言之:问题在于onBlur shadows onClick,所以运行按钮需要单击两次。我希望能够单击“运行”按钮,同时onBlur
和handleRunClick
fire
import React, { Component } from "react";
import { Controlled as CodeMirror } from "react-codemirror2";
import CellResults from "./CellResults";
import CellToolbar from "../Shared/CellToolbar";
import AddCellButton from "../Shared/AddCellButton";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/darcula.css";
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/ruby/ruby.js";
import "codemirror/mode/python/python.js";
class CodeCell extends Component {
state = {
code: this.props.cell.code
};
handleChange = value => {
this.setState({ code: value });
};
handleBlur = () => {
this.props.onUpdateCodeState(this.state.code, this.props.cellIndex);
if (this.props.language === "Markdown") {
this.props.toggleRender(this.props.cellIndex);
}
};
render() {
const cell = this.props.cell;
const cellOptions = {
mode: cell.type.toLowerCase(),
theme: "darcula",
lineNumbers: true,
showCursorWhenSelecting: true
};
return (
<div>
<div className="add-cell-container">
<AddCellButton
className="add-cell-btn"
onClick={this.props.onAddClick}
cellIndex={this.props.cellIndex}
/>
</div>
<CellToolbar
cellIndex={this.props.cellIndex}
onDeleteClick={this.props.onDeleteClick}
language={cell.type}
onLanguageChange={this.props.onLanguageChange}
rendered={cell.rendered}
onRunClick={this.props.onRunClick}
/>
<CodeMirror
value={this.state.code}
options={cellOptions}
onBeforeChange={(editor, data, value) => {
this.handleChange(value);
}}
onBlur={this.handleBlur}
/>
{cell.type !== "Markdown" ? (
<CellResults language={cell.type} results={cell.results} />
) : null}
</div>
);
}
}
export default CodeCell;
与上面的问题相关,当我单击其他按钮时,我会遇到相同的问题,例如,当我想单击创建下拉列表以插入新单元格的按钮时。如果元素的类型是button,我尝试过使用
e.relatedTarget.dropdown()
,但这并没有起作用,因为它说dropdown()
不是函数。Dropdown是使用bootstrapDropdownButton
实现的。我无法将Dropdown button show属性的状态更改为true
的原因之一可能是,当在handleBlur
中调用onUpdateCodeState
时,我试图在callback中设置状态,它说react不能在卸载的组件中执行状态更新。因此,onUpdateCodeState
卸载组件,但不确定如何处理。
import React from "react";
import Button from "react-bootstrap/Button";
class RunCellButton extends React.Component {
handleRunClick = () => {
this.props.onClick(this.props.cellIndex);
};
render () {
return (
<Button
className="run-button"
onClick={this.handleRunClick}
variant="secondary"
size="sm"
>
<span>►</span>
</Button>
);
}
};
export default RunCellButton;
import React, { Component } from "react";
import SplitButton from "react-bootstrap/SplitButton";
import * as constants from "../../Constants/constants";
import DropdownButton from "react-bootstrap/DropdownButton";
import Dropdown from "react-bootstrap/Dropdown";
class AddCellButton extends Component {
state = {
show: false
}
handleSelectCellType = language => {
this.props.onClick(this.props.cellIndex, language);
};
handleToggle = () => {
this.setState((prevState) => {
return {
show: !prevState["show"]
}
})
}
render() {
const dropDownItems = constants.LANGUAGES.map(language => {
return (
<Dropdown.Item
as="button"
value={language}
key={language}
eventKey={language}
>
{language}
</Dropdown.Item>
);
});
console.log("state of show " + this.state.show)
return (
<DropdownButton
show={this.state.show}
onToggle={this.handleToggle}
className="add-cell-btn"
variant="secondary"
id="dropdown-basic-button"
title={<span>+</span>}
size="sm"
onSelect={this.handleSelectCellType}
>
{dropDownItems}
</DropdownButton>
);
}
}
export default AddCellButton;