我有一个简单的块,下面的代码,其中包含一个组件,获取图像数据,包括一个URL和一个pid,使用自定义REST调用。registerBlockType编辑方法包含组件、显示图像和一个数字控件。在组件的componentDidUpdate() &componentDidMount()方法,当数字控件的值发生变化时,获取新数据并相应地更新图像显示。这很好;图像更新,当我保存使用页面编辑器中的更新按钮时,我可以刷新编辑器和块加载更新的图像。但是,当我尝试预览页面时,保存方法中既没有调用DidMount也没有调用diduupdate,预览页面显示我的图像加载失败消息。知道我是怎么处理的吗?
index.js:
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
import { __experimentalNumberControl as NumberControl } from '@wordpress/components';
import {PnImage} from './PnImage.js'
registerBlockType( 'create-block/pn-test', {
attributes: {
pid: {
type: "number",
default: 8
},
},
edit: ( {attributes, setAttributes} ) => {
console.log( "Edit", attributes )
return (
<p { ...useBlockProps() }>
{"Editoor " + attributes.pid}
<PnImage pid={attributes.pid}/>
<NumberControl
label="PID"
isShiftStepEnabled={ true }
onChange={ value => { setAttributes( {pid: value})} }
shiftStep={ 10 }
value={ attributes.pid }
/>
</p>
)
},
save: ({ attributes }) => {
return (
<p { ...useBlockProps.save() }>
{ "Saved " + attributes.pid}
<PnImage pid={attributes.pid}/>c
</p>
)
}
})
PnImage.js组件代码
import React, { Component } from 'react';
export class PnImage extends Component {
static defaultProps = {
size: "large",
pid: null,
}
constructor(props) {
super(props);
this.state = {
image: null,
pid: null
};
}
componentDidMount() { // initially fetch data
console.log( "DidMount, pid: ", this.props.pid)
this.Fetch()
}
componentDidUpdate() { // fetch data when props.pid changes
console.log( "DidUpdate, pid: ", this.props.pid)
this.Fetch()
}
render() {
const {image} = this.state;
return (
<p>
Image Component<br/>
{ image ? <img src={image.URL} /> : "no image found loaded for pid " + this.props.pid }
</p>
)
}
Fetch() { // fetch wrapper
if (this.props.pid != this.state.pid && this.props.pid ) {
console.log( "fetching: pid=", this.props.pid )
pnRest.Fetch('image/get', { pid: this.props.pid, size: this.props.size })
.then(data => {
if ( data ) { // image not found returns undefined
this.setState({ image: data, pid: data.id })
} else {
console.log( "Couldn't find image for pid " + this.props.pid )
}
});
}
}
}
我不认为你可以在save()
函数内运行异步函数。因此它永远不会保存返回的数据。相反,你应该做的是获取数据,然后将获取的数据保存到块的属性中(例如pid
和src
)。然后在save()
函数中使用这些保存的属性。您可以将setAttributes()
函数作为prop传递到PnImage
类中,并直接访问它:
<PnImage
pid={ attributes.pid }
setAttributes={ setAttributes }
/>
然后,在Fetch() {}
中,像这样:
pnRest.Fetch('image/get', {
pid: this.props.pid,
size: this.props.size
}).then(data => {
if (data) {
this.props.setAttributes({
src: data.src,
pid: data.id
});
}
);
经过一番折腾,我想出了一个解决方案。工作与菲尔的建议,而不是传递setAttributes到pnImage组件,我已经转移了Fetch函数到我的编辑函数,使用它在数字控制回调和,所以组件可以填充时,它第一次挂载,我传递Fetch到组件,并在componentDidMount调用它。看起来效果不错。
谢谢你的帮助,Phil。
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
import { __experimentalNumberControl as NumberControl } from '@wordpress/components';
import {PnImage} from './PnImage.js'
registerBlockType( 'create-block/pn-test', {
attributes: {
pid: {
type: "number",
default: 8
},
image: {
type: "object",
default: null
},
},
edit: ( {attributes, setAttributes} ) => {
console.log( "Edit", attributes )
function Fetch( pid ) { // fetch wrapper
pnRest.Fetch('image/get', { pid: pid, size: 'large' })
.then(data => {
if ( data ) { // image not found returns undefined
setAttributes({ image: data, pid: pid })
} else {
console.log( "Couldn't find image for pid <" + pid + ">" )
setAttributes({ image: null, pid: -1 })
}
});
}
return (
<p { ...useBlockProps() }>
<PnImage
pid={attributes.pid}
image={attributes.image}
Fetch={Fetch}
/>
<NumberControl
label="PID"
isShiftStepEnabled={ true }
onChange={ value => { if ( value == "" ) {return }; Fetch( value ) } }
shiftStep={ 10 }
value={ attributes.pid }
/>
</p>
)
},
save: ({ attributes, setAttributes }) => {
return (
<p { ...useBlockProps.save() }>
<PnImage
pid={attributes.pid}
image={attributes.image}
/>
</p>
)
}
})
import React, { Component } from 'react';
export class PnImage extends Component {
static defaultProps = {
size: "large",
pid: null,
image: null,
Fetch: null
}
constructor(props) {
super(props);
this.state = {
image: null,
pid: null
};
}
componentDidMount() { // initially fetch data
console.log( "DidMount, pid: ", this.props.pid)
this.props.Fetch( this.props.pid )
}
render() {
const image = this.props.image;
if ( this.props.pid == -1 ) {
return (
<p>
Image couldn't be fetched
</p>
)
}
return (
<p>
Image Component<br/>
{ image ? <img src={image.URL} /> : "no image found loaded for pid " + this.props.pid }
</p>
)
}
}