This is probably as simple case of either not understanding JavaScript/ESNext scoping or function passing (or both), but, I can’t get setAttributes to work outside of the primary "return" of my edit function. I’ve tried a gazillion different variations on this theme, with the two below being the closest. In the first, it seems to kind-of work, but maybe there’s a scoping problem. In the second, it seems passing the function to a component isn’t working. The first thing I tried was just using it, trying to work from how they did it in gutenberg/image-editor.js but that’s resulting in strange behavior:
export default function Edit( props ) {
const {
attributes: { cwraggDataSourceType, cwraggDataSource,
cwraggLocalFile },
setAttributes,
} = props;
...
const DataButton = ( ) => {
return (<Button
isPrimary
onClick={ doValidate }>{ __("Validate",
'cwra-google-graph-block')}</Button>);
}
...
const doValidate = ( ) => {
console.log('DataSourceType', cwraggDataSourceType); // logs "DataSourceType undefined ... this is fine
console.log('DataSource', cwraggDataSource); // logs the value previously saved in the attribute cwraggDataSource ... this is good
console.log('LocalFile', cwraggLocalFile); // always logs undefined, so the attribute isn't being saved
console.log('Doing validation');
apiFetch( {
path: '/cwraggb/v1/setremotedatasrc',
method: 'POST',
data: { 'url': cwraggDataSource,
'type': cwraggDataSourceType,
'postId': post_id } }
).then( ( localFileName ) => {
console.log("Working with ", localFileName); // logs "Working with tmptesty-ZatdoP.tmp" which is fine and means the API call worked
setAttributes( { cwraggLocalFile: localFileName } );
console.log('I still have ', localFileName); // still fine
console.log('cwraggLocalFile is ', cwraggLocalFile); // logs "cwraggLocalFile is undefined" so ... the setAttribute call didn't work?
}).catch( ( error ) => {
console.log('doh!'); // we never get here (yay!)
});
};
return (
<Fragment>
<div>
<DataSrcSelectControl />
<DataButton />
</div>
<div>
<TextControl
label={ __( 'Data URL', 'cwra-google-graph-block' ) }
help={ __( 'Enter the URL from which to get '
+ 'a JSON file with the data for the graph.',
'cwra-google-graph-block') }
value={ cwraggDataSource }
onChange={ (dataSource) => {
setAttributes( { cwraggDataSource: dataSource } ) // this works fine
}} />
</div>
<div className={ "it_worked" }>Generating graph from
{ cwraggDataSource }</div>
<div>Local data source is { cwraggLocalFile }</div> // this outputs "Local data source is tmptesty-ZatdoP.tmp" after I press the button, but if I update and reload the page, it outputs "Local data source is" and the attribute is empty????
</Fragment>
);
}
The cwraggLocalFile variable is not successfully logged to the console on button push (it logs undefined
), but is updated in the return
output after button push, but isn’t saved (after I press "Update" for the post, it’s still there, but when I reload the page, it’s gone. I can’t tell what’s happening here. It appears the setAttribute call both is and isn’t working, so … I’m thinking I have some scoping issue?
After much fiddling, I couldn’t get that to work, so I tried another approach, similar to this, where he passed the setAttributes function to his competent. I didn’t think I should have to do that, because he’s doing it in a clearly different scope, but I’m trying anything now:
const doValidate = ( (localFileName, setAttributes) => {
console.log('Was passed', localFileName);
console.log('Doing validation');
let dst = default_dst;
if (cwraggDataSourceType) {
dst = cwraggDataSourceType;
}
console.log('Using dst ', dst);
apiFetch( {
path: '/cwraggb/v1/setremotedatasrc',
method: 'POST',
data: { 'url': cwraggDataSource,
'type': dst,
'postId': post_id } }
).then( ( localFileName ) => {
console.log('API returned ', localFileName); // still works fine to here
setAttributes( { cwraggLocalFile: localFileName } );
console.log('Got local file name ', localFileName);
console.log('cwraggLocalFile is ', cwraggLocalFile);
}).catch( ( error ) => {
console.log('doh!', error); // but then we get here! It doesn't like setAttributes
});
});
return (
<Fragment>
<div>
<DataSrcSelectControl />
<Button isPrimary
onClick={ doValidate( {cwraggLocalFile},
{setAttributes}) }>{
__("Validate",
'cwra-google-graph-block')}</Button>
...
Attempting to use this method, it falls through to the error handler, and says
TypeError: setAttributes is not a function. (In 'setAttributes({ cwraggLocalFile: localFileName })', 'setAttributes' is an instance of Object)
(anonymous function) — edit.js:95
promiseReactionJob
So, I guess I’m passing the setAttributes function incorrectly. But, the fact that that’s happening and tripping the error here, but not in the first effort above, makes me think I was closer to doing things the Right Way in the first attempt.
Any ideas what I’m doing wrong, or how to use setAttibutes in places other than the main return
call?