I’m migrating my front-end code for a plugin to React and ESNext, and am still new to all of this, but for some reason, this really simple for
loop isn’t executing on the admin edit page, but is fine when viewing the post. The only thing I can see is that there seems to be a weird issue with how HTMLCollections are counted, on the back end. I have this code:
/*
* external dependencies
*/
import * as React from "react";
import { render } from "react-dom";
export default class App extends React.Component {
render() {
return (
<div className={"myapp-container"}>
// this is a test
</div>
);
}
}
document.addEventListener("DOMContentLoaded", (event) => {
let els = document.getElementsByClassName("myapp_wrapper_class");
console.log("got elements ", els); // this fires fine, everywhere
for (let el of els) {
console.log("working with ", el); // this fires on the front-end, but not in the editor
render(<App />, document.getElementById(el.id));
}
});
When I look at the console, on the front end, it logs
got elements
HTMLCollection (1) // note this "1"
0 <div id="myApp1" style="width: 100%; height: 300px;" class="myapp myapp_wrapper_class" data-cwragc-src="https://localhost:8888/wp-content/uploads/2021/01/nakaza.csv" data-cwragc-type="line"></div>
but in the editor, it logs
got elements
HTMLCollection (0) // note this "0"
0 <div id="myApp1" style="width: 100%; height: 300px;" class="myapp myapp_wrapper_class" data-cwragc-src="https://localhost:8888/wp-content/uploads/2021/01/nakaza.csv" data-cwragc-type="line"></div>
I’m unsure whether that zero is the problem, but like I said, it’s the only thing I can see that’s weird. There are no error messages in the console. I am sure that the for
loop isn’t being executed on the back end, even though the element is there (as you can see in the console log), and exists in the rendered DOM.
The elements are created with a server-side render. In the block’s edit function, it looks thusly:
export function MyAppEdit( props ) {
//...
const MyAppRender = () => {
return(
<Disabled>
<ServerSideRender
block={ props.name }
attributes={{ ...attributes }} />
</Disabled>
);
}
//...
return (
<>
{ controls }
<div { ...blockProps }>
{ cwragcLocalFile && <MyAppRender /> }
{ myAppPlaceholder }
</div>
</>
);
}
export default withNotices( MyAppEdit );
Grasping at straws, I also tried removing the <Disabled>
wrapper on the editor side, but no change in effect.
Basically, I have no idea what’s going on here, but I’d like my stuff to render on the back end 🙂
Is it possibly a Babel bug? Is there some difference/timing/race issue with when DOMContentLoaded
fires on the back end? Is there some better/more naturally React way for me to add a component to a div
when I don’t know how many of them there will be (other than getElementsByClassName
after DOMContentLoaded
?
For completeness’ sake, my webpack is this:
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
const path = require('path');
module.exports = {
...defaultConfig,
entry: {
myAppAdmin:
path.resolve( process.cwd(), 'admin/src', 'index.js' ),
myAppPublic:
path.resolve( process.cwd(), 'public/src', 'index.js' ),
},
output: {
filename: '(name).js',
path: path.resolve( process.cwd(), 'assets/js' ),
},
}
Maybe I’m missing some other require
? But, like I said, it’s not generating any errors. admin/src/index.js
is the block code; public/src/index.js
is front-end code I’m trying to migrate, that adds React stuff after the server-side render.