从父访问 draftjs 输出
Accessing draftjs output from parent
我有一个网站,我们在同一页面上使用多个表单。
我使用 Draftjs 和 React 来创建丰富的 html 文本输入,我已将其自定义为仅使用我实际需要的控件:
class RichEditor extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.focus = () => this.refs.editor.focus();
this.onChange = (editorState) => {
this.setState({editorState});
}
this.handleKeyCommand = (command) => this._handleKeyCommand(command);
this.onTab = (e) => this._onTab(e);
this.toggleBlockType = (type) => this._toggleBlockType(type);
this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
}
_handleKeyCommand(command) {
const {editorState} = this.state;
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
_onTab(e) {
const maxDepth = 4;
this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth));
}
_toggleBlockType(blockType) {
this.onChange(
RichUtils.toggleBlockType(
this.state.editorState,
blockType
)
);
}
_toggleInlineStyle(inlineStyle) {
this.onChange(
RichUtils.toggleInlineStyle(
this.state.editorState,
inlineStyle
)
);
}
render() {
const { editorState } = this.state;
let className = 'RichEditor-editor';
var contentState = editorState.getCurrentContent();
if (!contentState.hasText()) {
if (contentState.getBlockMap().first().getType() !== 'unstyled') {
className += ' RichEditor-hidePlaceholder';
}
}
return (
<div className="RichEditor-root">
<BlockStyleControls
editorState={editorState}
onToggle={this.toggleBlockType}
/>
<InlineStyleControls
editorState={editorState}
onToggle={this.toggleInlineStyle}
/>
<div className={className} onClick={this.focus}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
onTab={this.onTab}
placeholder=""
ref="editor"
spellCheck={true}
/>
</div>
</div>
);
}
}
module.exports = RichEditor
我的父组件如下所示:
class WrapperComponent extends React.Component {
constructor(props) {
super(props);
this.onChange = (editorState2) => {
this.setState({editorState2});
console.log("onChange");
console.log(editorState2);
}
this.state = {
editorState1: EditorState.createEmpty(),
editorState2: EditorState.createEmpty(),
html: null
}
}
update() {
console.log("update");
console.log(this.state.editorState2);
console.log(convertToRaw(this.state.editorState2.getCurrentContent()));
//this.setState({ draftEditor2: e.value });
this.setState({ html: stateToHTML(this.state.editorState2.getCurrentContent()) });
}
render () {
const Editable = () => (
<div className="editor">
<div className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" name="title" />
<h4>Text 1</h4>
<RichEditor editorState={this.state.editorState1} updateStateToParent={this.onChange} name="text01" ref="editor" />
<h4>Citat</h4>
<input type="text" name="quote01" />
<h4>Text 2</h4>
<RichEditor updateStateToParent={this.onChange} name="text02" ref="editor" />
<EditorFooter {...this.props} submitForm={this.submitForm} />
<button onClick={this.update.bind(this)}>Update</button>
<div>{this.state.html}</div>
</div>
</div>
);
const Readable = () => (
<div>
<h1 className="header66">{this.props.title}</h1>
<div className="text66">{this.props.text01}</div>
<div className="quote100">{this.props.quote01}</div>
<div className="text66">{this.props.text02}</div>
</div>
);
return (
<div>
{ this.props.isInEditMode ? <Editable /> : <Readable /> }
</div>
);
}
};
WrapperComponent.defaultProps = {
height: 100,
title: "Lorem ipsum dolor sit amet",
text01: "Mauris sollicitudin purus accumsan libero fringilla, vitae vulputate lorem aliquam. Nunc ipsum nisl, consectetur ac ultrices ac, pretium vitae lectus. Cras vestibulum, arcu non condimentum hendrerit, dolor ante molestie ante, eget dapibus felis quam a ante. Nunc fringilla risus eget nunc tincidunt sodales.",
quote01: "Aliquam erat volutpat.",
text02: "Praesent non erat quis sem mollis sodales. Integer convallis metus in ligula vehicula, quis vulputate lectus accumsan. Aliquam luctus posuere mollis. Aliquam luctus dignissim quam, ut aliquet ligula pellentesque ac. Nulla sodales lacus sem, eu pharetra arcu aliquet ac. Sed in venenatis libero."
};
WrapperComponent.propTypes = {
content: PropTypes.object,
itemId: PropTypes.string
}
module.exports = WrapperComponent
但我似乎误解了一些基本的东西。我无法从任何一位编辑那里获得价值。
如果我将 updateStateToParent
发送到我的 RichEditor
我可以看到一些事情发生,但我无法从 RichEditor
获取状态并将其添加到WrapperComponent
.
我认为我以错误的方式处理这个问题,但我不知道如何解决它。
我认为你在这里非常接近,但问题是你没有使用父级来设置 editorStates。您应该做的是在父组件中存储和更新 editorState。
这意味着 RichEditor
-组件必须:
- 接收其 editorState 作为 prop
- 告诉它的父级它里面的变化,让父级更新editorState(它又会被再次传递下去)。
这是一个最小的例子:
class RichEditor extends React.Component {
render() {
const { editorState, onChange } = this.props;
return (
<div style={{ background: 'white' }}>
<Editor editorState={editorState} onChange={onChange} />
</div>
);
}
}
父级必须:
- 为每个
RichEditor
创建初始 editorStates(并向下传递)
- 每次更改时更新这些 editorsStates
这是一个最简单的例子:
class WrapperComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState1: EditorState.createEmpty(),
editorState2: EditorState.createEmpty()
}
}
onChange = (editorStateKey) => (editorState) => {
this.setState({ [editorStateKey]: editorState });
}
render () {
return (
<div>
<h4>Editor 1</h4>
<RichEditor editorState={this.state.editorState1} onChange={this.onChange('editorState1')} />
<h4>Editor 2</h4>
<RichEditor editorState={this.state.editorState2} onChange={this.onChange('editorState2')} />
</div>
)
}
};
最后,这是一个有效的 fiddle:https://jsfiddle.net/bwk32xuo/
我有一个网站,我们在同一页面上使用多个表单。 我使用 Draftjs 和 React 来创建丰富的 html 文本输入,我已将其自定义为仅使用我实际需要的控件:
class RichEditor extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.focus = () => this.refs.editor.focus();
this.onChange = (editorState) => {
this.setState({editorState});
}
this.handleKeyCommand = (command) => this._handleKeyCommand(command);
this.onTab = (e) => this._onTab(e);
this.toggleBlockType = (type) => this._toggleBlockType(type);
this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
}
_handleKeyCommand(command) {
const {editorState} = this.state;
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
_onTab(e) {
const maxDepth = 4;
this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth));
}
_toggleBlockType(blockType) {
this.onChange(
RichUtils.toggleBlockType(
this.state.editorState,
blockType
)
);
}
_toggleInlineStyle(inlineStyle) {
this.onChange(
RichUtils.toggleInlineStyle(
this.state.editorState,
inlineStyle
)
);
}
render() {
const { editorState } = this.state;
let className = 'RichEditor-editor';
var contentState = editorState.getCurrentContent();
if (!contentState.hasText()) {
if (contentState.getBlockMap().first().getType() !== 'unstyled') {
className += ' RichEditor-hidePlaceholder';
}
}
return (
<div className="RichEditor-root">
<BlockStyleControls
editorState={editorState}
onToggle={this.toggleBlockType}
/>
<InlineStyleControls
editorState={editorState}
onToggle={this.toggleInlineStyle}
/>
<div className={className} onClick={this.focus}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
onTab={this.onTab}
placeholder=""
ref="editor"
spellCheck={true}
/>
</div>
</div>
);
}
}
module.exports = RichEditor
我的父组件如下所示:
class WrapperComponent extends React.Component {
constructor(props) {
super(props);
this.onChange = (editorState2) => {
this.setState({editorState2});
console.log("onChange");
console.log(editorState2);
}
this.state = {
editorState1: EditorState.createEmpty(),
editorState2: EditorState.createEmpty(),
html: null
}
}
update() {
console.log("update");
console.log(this.state.editorState2);
console.log(convertToRaw(this.state.editorState2.getCurrentContent()));
//this.setState({ draftEditor2: e.value });
this.setState({ html: stateToHTML(this.state.editorState2.getCurrentContent()) });
}
render () {
const Editable = () => (
<div className="editor">
<div className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" name="title" />
<h4>Text 1</h4>
<RichEditor editorState={this.state.editorState1} updateStateToParent={this.onChange} name="text01" ref="editor" />
<h4>Citat</h4>
<input type="text" name="quote01" />
<h4>Text 2</h4>
<RichEditor updateStateToParent={this.onChange} name="text02" ref="editor" />
<EditorFooter {...this.props} submitForm={this.submitForm} />
<button onClick={this.update.bind(this)}>Update</button>
<div>{this.state.html}</div>
</div>
</div>
);
const Readable = () => (
<div>
<h1 className="header66">{this.props.title}</h1>
<div className="text66">{this.props.text01}</div>
<div className="quote100">{this.props.quote01}</div>
<div className="text66">{this.props.text02}</div>
</div>
);
return (
<div>
{ this.props.isInEditMode ? <Editable /> : <Readable /> }
</div>
);
}
};
WrapperComponent.defaultProps = {
height: 100,
title: "Lorem ipsum dolor sit amet",
text01: "Mauris sollicitudin purus accumsan libero fringilla, vitae vulputate lorem aliquam. Nunc ipsum nisl, consectetur ac ultrices ac, pretium vitae lectus. Cras vestibulum, arcu non condimentum hendrerit, dolor ante molestie ante, eget dapibus felis quam a ante. Nunc fringilla risus eget nunc tincidunt sodales.",
quote01: "Aliquam erat volutpat.",
text02: "Praesent non erat quis sem mollis sodales. Integer convallis metus in ligula vehicula, quis vulputate lectus accumsan. Aliquam luctus posuere mollis. Aliquam luctus dignissim quam, ut aliquet ligula pellentesque ac. Nulla sodales lacus sem, eu pharetra arcu aliquet ac. Sed in venenatis libero."
};
WrapperComponent.propTypes = {
content: PropTypes.object,
itemId: PropTypes.string
}
module.exports = WrapperComponent
但我似乎误解了一些基本的东西。我无法从任何一位编辑那里获得价值。
如果我将 updateStateToParent
发送到我的 RichEditor
我可以看到一些事情发生,但我无法从 RichEditor
获取状态并将其添加到WrapperComponent
.
我认为我以错误的方式处理这个问题,但我不知道如何解决它。
我认为你在这里非常接近,但问题是你没有使用父级来设置 editorStates。您应该做的是在父组件中存储和更新 editorState。
这意味着 RichEditor
-组件必须:
- 接收其 editorState 作为 prop
- 告诉它的父级它里面的变化,让父级更新editorState(它又会被再次传递下去)。
这是一个最小的例子:
class RichEditor extends React.Component {
render() {
const { editorState, onChange } = this.props;
return (
<div style={{ background: 'white' }}>
<Editor editorState={editorState} onChange={onChange} />
</div>
);
}
}
父级必须:
- 为每个
RichEditor
创建初始 editorStates(并向下传递) - 每次更改时更新这些 editorsStates
这是一个最简单的例子:
class WrapperComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState1: EditorState.createEmpty(),
editorState2: EditorState.createEmpty()
}
}
onChange = (editorStateKey) => (editorState) => {
this.setState({ [editorStateKey]: editorState });
}
render () {
return (
<div>
<h4>Editor 1</h4>
<RichEditor editorState={this.state.editorState1} onChange={this.onChange('editorState1')} />
<h4>Editor 2</h4>
<RichEditor editorState={this.state.editorState2} onChange={this.onChange('editorState2')} />
</div>
)
}
};
最后,这是一个有效的 fiddle:https://jsfiddle.net/bwk32xuo/