在 parent 的状态改变后反应更新 child 的道具
React update child's props after parent's state change
我正在尝试将 Draft.js 的编辑器状态从编辑器组件传递到我自己的 Sidebar
组件。
使用最顶层的组件 Notes
我使用回调从 CustomEditor
获取编辑器状态并将其设置为 Notes
状态。然后我将该状态作为道具传递给 Sidebar
。
问题是 prop 是在回调触发之前设置的。我在想 setTimeout
但这似乎很粗糙。我知道 UNSAFE_componentWillReceiveProps()
但文档不推荐它。这个用例有反应吗?
export class Notes extends Component {
constructor(props) {
super(props);
this.getEditorState = this.getEditorState.bind(this)
this.state = {
editorState: "the placeholder data Sidebar should not have as a prop"
};
}
getEditorState(state) {
console.log(state)
this.setState({editorState: state})
}
render() {
return (
<section id="Notes">
<div id="editor-holder">
<Sidebar currentEditorState={this.state.editorState}/>
<div id="Editor">
<FileHeader />
<CustomEditor getState={this.getEditorState}/>
</div>
</div>
</section>
);
}
}
export default Notes;
好吧,还有更多可能的选择来实现这个结果
条件渲染
只有当道具改变了 menas
时,您才能渲染 <Sidebar>
constructor(props)
super(props)
this.state = {
editorState: false
}
}
render() {
... {this.state.editorState && <Sidebar currentEditorState={this.state.editorState}/>}
}
undefined/false 道具的保护组件
Sidebar.js
render() {
if(!this.props.currentEditorState) return null // this will force React to render nothing
return ( ... )
}
使用 getDerivedState 将道具转换为状态
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
Sidebar.js
static getDerivedStateFromProps({ currentEditorState }, prevState) {
if(currentEditorState !== false {
return { currentEditorState }
} else {
return {}
}
}
render() {
(.... something bound to this.state.currentEditorState)
}
使用上下文(遗留上下文)
class Notes extends React.Component {
getEditorState(state) {
console.log(state)
this.setState({editorState: state})
}
getChildContext() {
return {
editorState: this.state.editorState
}
}
childContextTypes = {
editorState: PropTypes.oneOfType([PropTypes.obj, PropTypes.bool])
}
}
Sidebar.js
class Sidebar {
static contextTypes = {
editorState: PropTypes.oneOfType([PropTypes.obj, PropTypes.bool])
}
render() {
... this.context.editorState
}
}
新的 Context API 是解决此类问题的方法。花了一点时间来理解它,但我想出的是 editorState
到 Sidebar
作为道具。
export const NoteContext = React.createContext("placeholderEditorState");
export class Notes extends Component {
constructor(props) {
super(props);
this.getEditorState = this.getEditorState.bind(this)
this.getFolderData = this.getFolderData.bind(this)
this.state = {
editorState: null,
folderData: null
};
}
getEditorState(state) {
this.setState({editorState: state});
}
getFolderData(data) {
this.setState({folderData : data})
}
render() {
return (
<section id="Notes">
<TopBar />
<div id="editor-holder">
<NoteContext.Provider value={{editorState: this.state.editorState}} >
<NoteContext.Consumer>
{(context)=>{ return (
<Sidebar currentEditorState={context.editorState} getFolderData={this.getFolderData}/>
)}}
</NoteContext.Consumer>
</NoteContext.Provider>
<div id="Editor">
<NoteContext.Provider value={{folderData: this.state.folderData}} >
<FileHeader />
</NoteContext.Provider>
<CustomEditor getState={this.getEditorState}/>
</div>
</div>
</section>
);
}
}
现在看来很简单,也算是学到了很多东西!让我知道我是否可以在这里改进任何内容。
我正在尝试将 Draft.js 的编辑器状态从编辑器组件传递到我自己的 Sidebar
组件。
使用最顶层的组件 Notes
我使用回调从 CustomEditor
获取编辑器状态并将其设置为 Notes
状态。然后我将该状态作为道具传递给 Sidebar
。
问题是 prop 是在回调触发之前设置的。我在想 setTimeout
但这似乎很粗糙。我知道 UNSAFE_componentWillReceiveProps()
但文档不推荐它。这个用例有反应吗?
export class Notes extends Component {
constructor(props) {
super(props);
this.getEditorState = this.getEditorState.bind(this)
this.state = {
editorState: "the placeholder data Sidebar should not have as a prop"
};
}
getEditorState(state) {
console.log(state)
this.setState({editorState: state})
}
render() {
return (
<section id="Notes">
<div id="editor-holder">
<Sidebar currentEditorState={this.state.editorState}/>
<div id="Editor">
<FileHeader />
<CustomEditor getState={this.getEditorState}/>
</div>
</div>
</section>
);
}
}
export default Notes;
好吧,还有更多可能的选择来实现这个结果
条件渲染
只有当道具改变了 menas
时,您才能渲染<Sidebar>
constructor(props)
super(props)
this.state = {
editorState: false
}
}
render() {
... {this.state.editorState && <Sidebar currentEditorState={this.state.editorState}/>}
}
undefined/false 道具的保护组件
Sidebar.js
render() {
if(!this.props.currentEditorState) return null // this will force React to render nothing
return ( ... )
}
使用 getDerivedState 将道具转换为状态
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
Sidebar.js
static getDerivedStateFromProps({ currentEditorState }, prevState) {
if(currentEditorState !== false {
return { currentEditorState }
} else {
return {}
}
}
render() {
(.... something bound to this.state.currentEditorState)
}
使用上下文(遗留上下文)
class Notes extends React.Component {
getEditorState(state) {
console.log(state)
this.setState({editorState: state})
}
getChildContext() {
return {
editorState: this.state.editorState
}
}
childContextTypes = {
editorState: PropTypes.oneOfType([PropTypes.obj, PropTypes.bool])
}
}
Sidebar.js
class Sidebar {
static contextTypes = {
editorState: PropTypes.oneOfType([PropTypes.obj, PropTypes.bool])
}
render() {
... this.context.editorState
}
}
新的 Context API 是解决此类问题的方法。花了一点时间来理解它,但我想出的是 editorState
到 Sidebar
作为道具。
export const NoteContext = React.createContext("placeholderEditorState");
export class Notes extends Component {
constructor(props) {
super(props);
this.getEditorState = this.getEditorState.bind(this)
this.getFolderData = this.getFolderData.bind(this)
this.state = {
editorState: null,
folderData: null
};
}
getEditorState(state) {
this.setState({editorState: state});
}
getFolderData(data) {
this.setState({folderData : data})
}
render() {
return (
<section id="Notes">
<TopBar />
<div id="editor-holder">
<NoteContext.Provider value={{editorState: this.state.editorState}} >
<NoteContext.Consumer>
{(context)=>{ return (
<Sidebar currentEditorState={context.editorState} getFolderData={this.getFolderData}/>
)}}
</NoteContext.Consumer>
</NoteContext.Provider>
<div id="Editor">
<NoteContext.Provider value={{folderData: this.state.folderData}} >
<FileHeader />
</NoteContext.Provider>
<CustomEditor getState={this.getEditorState}/>
</div>
</div>
</section>
);
}
}
现在看来很简单,也算是学到了很多东西!让我知道我是否可以在这里改进任何内容。