Skip to main content

Component values and visibility

When we say a component is 'controlled' or 'uncontrolled', we refer to two independent aspects of the component:

  • The value of the component.
  • The visibility of the component.

Among the components available to you, some have props with initial in the name. This means the component has an uncontrolled mode, and the initial\* prop can be used to define initial state. This doesn't mean the component also has controlled mode available. Unlike some legacy components, the new versions don't have props with default in the name.

note
  • There are legacy components (in @jutro/legacy) that behave differently than than those added in 10.0.
  • There are many components, such as DateField, that are included in version 10.0. These components behave like legacy components, but they have not been updated for the latest release.
  • This document describes the new components. To learn about legacy components, or older components that are included in the latest release, switch to a version of the docs older than 10.0.x.

Controlling the value

If you want to connect the component to the application state, use controlled mode. Alternatively, use uncontrolled components if you use the component to mainly display content.

To learn more, read about the concept of controlled vs. uncontrolled in React.

Inputs can be both controlled an uncontrolled. They have three props:

  • initialValue
  • value
  • onChange

Depending on what is passed, the component is either controlled or uncontrolled:

Making it controlled

  • Pass onChange and value, don't pass initialValue: controlled.
    You must keep the state somewhere in the application and pass it to the component.

  • Pass all: onChange, value, and initialValue: controlled.
    Same as above. initialValue is discarded.

    You have full control of the value of the component.

    const [value, setValue] = useState('initial value');

    <TextInput
    label="Controlled input"
    value={value}
    onChange={(e) => {
    setValue(e.target.value.toLocaleUpperCase());
    }}
    />;

Making it uncontrolled

  • Pass onChange, don't pass value and initialValue: uncontrolled.

    The user can interact with the component and update its internal state. You can react on value changes using onChange callback. You can't control the state of the component programatically.

  • Pass onChange and initialValue, don't pass value: uncontrolled.

    Same as above. Updates to initialValue are ignored.

    <TextInput
    label="Uncontrolled input"
    // initialValue="Initial value"
    onChange={(e) => {
    console.log(e.target.value);
    }}
    />

Controlling the visibility

The visibility of a component can be controlled in a number of ways, depending on the component being used.

  • Only with controlled mode: These components change visibility based on an external trigger. A good example of a controlled component is ModalNext. Learn about ModalNext and how it behaves in the Components section.

  • Only with uncontrolled mode: These components change visibility based on an internal trigger, for example the Accordion component. The initial state of the component might be set to 'initial'. Later, the state is managed within the component.

    The following Accordion example displays some content in tabs, but changing the tabs does not change anything in the application. Its main purpose is to show the content of the tabs. On first render, the open cards are determined by their initialExpanded prop.

    const UncontrolledAccordion = () => {
    return (
    <Accordion>
    <AccordionCard
    title="Card 1"
    initialExpanded={false}>
    Test card 1
    </AccordionCard>
    <AccordionCard
    title="Card 2"
    initialExpanded>
    Test card 2
    </AccordionCard>
    </Accordion>
    );
    };
  • Other components: These components don't control their visibility. They are not effected by the controllability aspect of components.

    const [showSomeButton, setShowSomeButton] = useState(true);
    return (
    <React.Fragment>
    <Button
    label="I can hide the other button"
    onClick={() => setShowSomeButton((show) => !show)}
    />
    {showSomeButton && <Button label="I can be hidden" />}
    </React.Fragment>
    );