2

I'm a bit of a rookie, so I may be looking at this all backwards - but if that is the case having someone point me in the right direction would be incredibly valuable!

I'm creating a few custom blocks and have been struggling through figuring out JSX, React, ES6 imports and exports, etc. But, I've noticed that I've been repeating myself a bit. For instance, many of my blocks will have a fairly identical option for selecting a background image and there are about 30 lines of code that I'm copy-pasting from block to block to allow for this.

My question is: Is there a way I can create a module or function that I can include instead of repeating this code over and over?

After a few hours I've just finished my first attempt, where I hit a stone wall trying to work out how to update/set the main block's properties from within another module. As when a new image is set, the image's ID and URL are added to the blocks attribute so they can be used later on. However, because I was processing the image and getting the ID in a separate module I couldn't save them to the main module/block's attributes.

I was thinking it could be possible to return all the needed values back to the main block and then set attributes there... but that felt like going further down the wrong path, so I thought I'd ask here instead!

Here's the code I'm looking to split off Into a separate module/file/element. It's all living in the "edit.js" file of a custom block at the moment - part of it is for getting the image's URL so it can be displayed in the editor, and the rest is for the actual UI in the settings sidebar/Inspector Controls

//Getting background images for editing preview
 useEffect(
  function () {
    if (attributes.backgroundImageMB) {
      async function go() {
        const response = await apiFetch({
          path: `/wp/v2/media/${attributes.backgroundImageMB}`,
          method: "GET"
        })
        setAttributes({ backgroundImageMB_URL: response.media_details.sizes.full.source_url })
      }
      go()
    }
  },
  [attributes.backgroundImageMB]
)

 //Background image selection handling
 function backgroundImageMB(x) {
  setAttributes( { backgroundImageMB: x.id} )
 }

And then:

<PanelRow>
      
      <div className={"jcc-settings_image-preview"}>
       <img src={attributes.backgroundImageMB_URL} />      
      </div>

      <MediaUploadCheck>
       <MediaUpload
        className={"jcc-settings_image"}
        onSelect={backgroundImageMB} 
        value={attributes.backgroundImageMB} 
        render={ ({ open }) => {
          return <button onClick={open}>Choose Image</button>
        }} 
       />
      </MediaUploadCheck>
     </PanelRow>
     <PanelRow>
      <Button 
       className={"jcc-settings__rm-bg"}
       variant="link"
       onClick={ ( e ) => setAttributes( { backgroundImageMB: " ", backgroundImageMB_URL:" " } ) }
      >
       Remove Background
      </Button>
     </PanelRow>
3
  • 2
    I am not willing to touch gutenberg with a 50 mile long stick ;) but you are doing an early optimization and early optimizations are usually waste of time. Experiance tells me that only when project is done you have enough information to understand which part of it might benefit from DRY and modalirization as only then you are sure there are parts in which you RY and have better insight on what future changes to the code might be required Commented Nov 10, 2024 at 11:25
  • It's frustrating to do something in a way that you know is going to bite you later, but what you're saying makes sense! I'm also starting to see why you stay so far away from Gutenberg ahah! Thanks for the comment dude. Commented Nov 10, 2024 at 14:51
  • 2
    There's a lot to unpack here... In short the answer would be to make your background image component a "Controlled Component" - that is, give it props to receive the current value, and a callback function which will be executed if the the user selects a new image. In this fashion the parent can supply a value and can respond to changes. You might also see this referred to as "lifting state up" within the React world. But that said, I think you might be reinventing <MediaPlaceholder> - maybe poke around a bit with that and see if it fulfills your needs. Commented Nov 10, 2024 at 16:32

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.