0

I'm trying to use the RangeControl component. This is what I'm doing:

el(
    RangeControl,
    {
        label: 'Columns',
        value: props.attributes.my_attribute,
        initialPosition: 1,
        min: 0,
        max: 3,
        onChange: function( val ) {
        }
    }
),

this works Ok, but If I specify a different variable in the value parameter (and setup my attribute through the onChange event, instead), then the component stops working (actually, the onChange event is fired, but the component doesn't render correctly moving the current value indicator).

var my_variable = 1;

el(
    RangeControl,
    {
        label: 'Columns',
        value: my_variable,
        initialPosition: 1,
        min: 0,
        max: 3,
        onChange: function( val ) {
            my_variable = val;
        }
    }
),

Is there something I'm missing here? Is this the intended behavior, or have I accidentally discovered a bug in the component?

Thank you!

2
  • What do you mean If I specify a different variable in the value parameter? Could you share the code?
    – Alvaro
    Commented Jan 7, 2019 at 13:32
  • @Alvaro, I've updated my original post
    – Andrea
    Commented Jan 7, 2019 at 13:38

1 Answer 1

1

When using a control that modifies a block attribute, you need to set the value of the control to the value of the attribute and the onChange function needs to change the attribute using the setAttributes function:

el(
    RangeControl,
    {
        label: 'Columns',
        value: props.attributes.my_attribute,
        initialPosition: 1,
        min: 0,
        max: 3,
        onChange: function( val ) {
            props.setAttributes({ my_attribute: val })
        }
    }
),

The above example is linked to a block. The block attributes modify the component state. If you want to modify the state by your own, you could link it to the redux store. Or you could simply use the state of the component through the withState HOC. To do so you would need to wrap your component inside withState and use the props provided by it to update it.

const { withState } = wp.compose;
const { Component } = wp.element;
const { RangeControl } = wp.components;

class Range extends Component {
    render() {
        const { my_number, setState } = this.props;

        return (
            <RangeControl
                value={my_number}
                min={0}
                max={3}
                onChange={value => {
                    setState({ my_number: value });
                }}
            />
        );
    }
}

export default withState({ my_number: 1 })(Range);
6
  • Using the setAttributes function works if I actually have an attribute that I want to modify directly. In this case, I'm trying to use the RangeControl component applied to a custom variable. I've edited my second example above (note the my_variable variable that's being used as value and updated when the control changes its value).
    – Andrea
    Commented Jan 7, 2019 at 13:56
  • @Andrea I'd rely on the attributes instead, it's better to use the data structures presented to you if you want to store them than it is to manage them yourself. Eitherway React/etc have no way to know that the variable changed if the props on the component never change, so there's no reason to re-render
    – Tom J Nowell
    Commented Jan 7, 2019 at 14:27
  • @Andrea, as TomJNowell says the way to modify attributes is using setAttributes. A different thing would be to use the component to modify a value which is not related to an attribute. If you could expand on the exact case maybe we can help you with a more specific solution.
    – Alvaro
    Commented Jan 7, 2019 at 14:56
  • @Alvaro, TomJNowell, that's exactly what I'm trying to do, "use the component to modify a value which is not related to an attribute". This way, I could potentially re-use the RangeControl component from within another component I could create. UI-wise, that would open up a lot of possibilities. How would you handle such a case?
    – Andrea
    Commented Jan 7, 2019 at 17:30
  • @Andrea in such case you will need to use the withState HOC so that the component has a state. React uses the state to manage component props, and it is what attributes actually modify (if I'm correct). I'll update the answer, but I only know how to use the ES6 syntax, hope its ok.
    – Alvaro
    Commented Jan 7, 2019 at 18:47

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.