Search code examples
javascriptwordpressecmascript-nextwordpress-gutenberg

How do I pass a key to a function in ESNext?


I'm writing a gutenberg block plugin for WordPress, but I'm having trouble wrapping my head around the new ESNext syntax. I have a list of fields with a key:value pairing. Here is the code that I have which is working:

{
  ...
  edit: function( { className, attributes, setAttributes } ) {
    return (
      <div className={ className }>
        <label className="field">
          <span className="field__label">Name</span>
          <PlainText
            className="field__input"
            id="email"
            value={ attributes.name }
            onChange={ ( name ) => setAttributes( { name } ) }
          />
        </label>
        <label className="field">
          <span className="field__label">Email</span>
          <PlainText
            className="field__input"
            id="email"
            value={ attributes.email }
            onChange={ ( email ) => setAttributes( { email } ) }
          />
        </label>
      </div>
    );
  }
  ...
}

I would like this code to be less repetitive and avoid the copy-paste. This is how far I got:

{
  edit: function( { className, attributes, setAttributes } ) {
    var fields = {
      name:    'Name',
      email:   'Email',
      phone:   'Phone',
      website: 'Website',
    }
    var html = [];
    for ( var field_key in fields ) {
      var label = fields[ field_key ];
      html.push( (
        <label className="field" key={field_key}>
          <span className="field__label">{ label }</span>
          <PlainText
            className="field__input"
            id={field_key}
            value={ attributes[field_key] }
            onChange={ ( ??? ) => setAttributes( { ??? } ) }
          />
        </label>
      ) );
    }
    return (
      <div className={ className }>
        {html}
      </div>
    );
  },
}

How do I pass the field_key variable into the setAttributes function?


Solution

  • You don't actually need the handler function to bind field_key. If you just pass an arrow function to onChange it will bind field_key and you can then pass it to setAttributes:

    for (const field_key in fields) {
      const label = fields[field_key];
    
      html.push(
        <label className="field" key={field_key}>
          <span className="field__label">{ label }</span>
          <PlainText
            className="field__input"
            id={field_key}
            value={ attributes[field_key] }
            onChange={() => { setAttributes({ [field_key]: fields[field_key] }); }}
           />
        </label>
      ); 
    }
    

    I put an example up on Codepen to illustrate this (React example but should work in your case as well).