Home > Back-end >  React input[type="range"] with custom tick labels
React input[type="range"] with custom tick labels

Time:08-24

I have the following React component:

  // Datalist for custom tick mark display
  const datalistId = `slider-datalist-${uniqueId()}`;
  const datalistItems = [];
  for (let i=min; i<=max; i  = stepSize) {
    if (labelRenderer) {
      datalistItems.push(<option key={i} value={i} label={labelRenderer(i)} />)
    } else {
      datalistItems.push(<option key={i} value={i} label={i} />)
    }
  }

  return (
    <div>
      <input
        type="range"
        id={id}
        value={value}
        min={min}
        max={max}
        step={stepSize}
        onChange={handleChange}
        list={datalistId}
      />
      <datalist id={datalistId}>
        {datalistItems}
      </datalist>
    </div>
  );

Things work fine with labelRenderer when a basic value (i.e. string or number) is provided:

    <Slider
      min={1} 
      max={10} 
      stepSize={1}
      labelRenderer={v => { 
        return `**${v}**`;
      }} 
    />

working tick labels

But things blow up when I try to get it to render React JSX:

    <Slider
      min={1} 
      max={10} 
      stepSize={1}
      labelRenderer={v => { 
        return (<span style={{ color: '#f00;' }}>{v}</span>);
      }} 
    />

bad tick labels

Does anyone know why? I would have expected React to handle the output here just fine.

CodePudding user response:

The label attribute casts everything as a string. So you have to find another way to render the different elements, if you just need to change the style, I think with the right names (like using data-color="#f00", for example) you can do it just from CSS.

CodePudding user response:

You are trying to pass a JSX object to an attribute of an HTML tag (option). Here, I've used input instead of option tag to clarify what exactly happens. Even if you pass JSX like this <option>{JSX here!}</option> I won't work because <option> doesn't support any nested tag.

   const ChildComponent = function({callBack}) {
      
      let aNumber = 10; 
      let theList = [<input value={callBack(aNumber)}/>,
      <div>{callBack(aNumber)} fixed</div>];
    
      return (<div>{theList}</div>);
    }
    
    
    export default function App() {
      return (
        <div className="App">
          <ChildComponent  callBack={num => {
            //return `${num}`;  // Converted to String
            return (<span>{num}</span>); // Return Object
          }} />
        </div>
      );
    }

https://codesandbox.io/s/blissful-jackson-k6bjt1?file=/src/App.js:24-469

  • Related