d3 v4 get Text Length per data value

So currently my setup is

<g>
  <rect/>
  <text/>
</g>

This is done multiple times based on how many labels are passed into my d3. I am trying to have the rect to be the width of the text pixel length. I am having trouble because my current code is causing only one text length to show (looks like the first value). I am unsure how to properly pass these needed calculations in between the two different elements and allow it to be calculated independently to which ever the label length is.

My current code is:

const legend = svg.selectAll('.label')
        .data(keys.slice().reverse())
        .enter()
      let legendGroup = legend.append('g')
        .attr('class', 'label')
        .attr('transform', 'translate(' + margin.left + ',' + (height + margin.bottom) + ')')

      legendGroup.append('text')
        .text(function (d) { return d })
        .attr('y', 15)

      legendGroup.append('rect')
        .attr('width', function () {
          console.log(d3.selectAll('.label').selectAll('text'))
          console.log(d3.selectAll('.label').selectAll('text').node().getComputedTextLength())
          return d3.selectAll('.label').selectAll('text').node().getComputedTextLength()
        })
        .attr('height', '20')
        .attr('fill', 'pink')

      relax(legendGroup)
    }
  }

  function relax (legendGroup) {
    let spacing = 120
    legendGroup.each(function (d, i) {
      let a = this
      let da = d3.select(a).select('rect')
      legendGroup.each(function (d, j) {
        let b = this
        if (a === b) return
        let db = d3.select(b).select('rect')
        let dbt = d3.select(b).select('text')
        da.attr('x', '0')
        let x2 = parseInt(db.attr('x'))
        db.attr('x', (x2 + spacing))
        dbt.attr('x', (x2 + spacing))
      })
    })
  }