23.2.5 • Published 8 days ago

devextreme-react v23.2.5

Weekly downloads
23,182
License
MIT
Repository
github
Last release
8 days ago

DevExtreme React UI and Visualization Components

Build Status Project Status NPM

This project allows you to use DevExtreme Widgets as React Components.

Getting Started

You can try this live example (no need to install anything).

If you’d rather use a local development environment check out the sections below.

Prerequisites

Node.js and npm are required

Install DevExtreme

Install the devextreme and devextreme-react npm packages:

npm install --save devextreme@18.1 devextreme-react

Additional Configuration

The further configuration steps depend on which build tool, bundler or module loader you are using. Please choose the one you need:

Use DevExtreme Components

import React from 'react';
import ReactDOM from 'react-dom';

import { Button } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

ReactDOM.render(
    <Button text='Example Button' />,
    document.getElementById('root')
);

Note that DevExtreme styles are required.

API Reference

The complete list of components and their APIs are described in the DevExtreme API Reference.

See Markup Customization for details on how to implement and apply templates.

State Management

DevExtreme React components support both Controlled and Uncontrolled state modes.

Controlled Mode

In the controlled mode, a parent component passes a component's state using its props. This mode provides the following capabilities:

  • Control component state externally (stateless behavior)
  • Share state between components in your app
  • Persist and restore state

To control a component's state, provide the value for the required property and handle the event that is fired when it is changed (use the appropriate property with the on prefix):

import React from 'react';
import ReactDOM from 'react-dom';

import { TextBox } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

class Example extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            text: 'TEXT'
        };

        this.handleChange = this.handleChange.bind(this);
    }

    render() {
        return (
            <div>
                <TextBox
                    value={this.state.text}
                    onValueChanged={this.handleChange}
                    valueChangeEvent='input'
                />
                <br />
                <div>{this.state.text}</div>
            </div>
        );
    }

    handleChange(e) {
        this.setState({
            text: e.value.toUpperCase().replace('A','_')
        });
    }
}

ReactDOM.render(
    <Example />,
    document.getElementById('root')
);

Live example

Uncontrolled Mode

Sometimes there is no need to handle all the component's updates, thus DevExtreme components can manage their state internally which reduces the amount of code required.

Note that if you want to specify an initial value for an option in the uncontrolled mode, you should use an appropriate property with the default prefix. In the example below, the currentView option's initial value is defined using the defaultCurrentView property.

import React from 'react';
import ReactDOM from 'react-dom';

import { Scheduler } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';
const appointments = [
    {
        text: 'Website Re-Design Plan',
        startDate: new Date(2017, 4, 22, 9, 30),
        endDate: new Date(2017, 4, 22, 11, 30)
    }, {
        text: 'Book Flights to San Fran for Sales Trip',
        startDate: new Date(2017, 4, 22, 12, 0),
        endDate: new Date(2017, 4, 22, 13, 0),
        allDay: true
    }, {
        text: 'Install New Router in Dev Room',
        startDate: new Date(2017, 4, 23, 10, 30),
        endDate: new Date(2017, 4, 23, 16, 30)
    }
];


ReactDOM.render(
    <Scheduler
        dataSource={appointments}
        height={600}
        editing={false}
        defaultCurrentView={'week'}
        defaultCurrentDate={new Date(2017, 4, 22)}
        startDayHour={9}
    />,
    document.getElementById('root')
);

Getting Widget Instance

In some cases, a widget instance is required when you need to call a widget method. You can get it by assigning a callback function to the component's ref property. This function accepts the mounted DevExtreme Component as an argument whose instance property stores the widget instance.

import React from 'react';
import ReactDOM from 'react-dom';

import { Button, TextBox } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

class Example extends React.Component {

    render() {
        return (
            <div>
                <TextBox ref={(ref) => this.textBox = ref.instance}/>
                <Button text='Go to the TextBox' onClick={() => this.textBox.focus()} />
            </div>
        );
    }
}

ReactDOM.render(
    <Example />,
    document.getElementById('root')
);

Markup Customization

You can customize widget elements' appearance via the corresponding template properties. In the DevExtreme API, the corresponding options have the Template suffix (e.g. dxList's itemTemplate option).

To specify a DevExtreme React Component template, use the Render or Component suffix instead. If a widget has an option called template (e.g. Button's template option) the corresponding React Component properties are called render and component.

Use a property with the Render suffix to specify a rendering function:

import React from 'react';
import ReactDOM from 'react-dom';

import { List } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

const items = [
    { text: '123' },
    { text: '234' },
    { text: '567' }
];

ReactDOM.render(
    <List items={items} itemRender={(item) => <i>Function template for item <b>{item.text}</b></i>}/>,
    document.getElementById('root')
);

Functional Components can cause unnecessary render calls. In such cases, consider using the PureComponent or the shouldComponentUpdate method.

A template component can be specified using a property with the Component suffix:

import React from 'react';
import ReactDOM from 'react-dom';

import { List } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

const items = [
    { text: '123' },
    { text: '234' },
    { text: '567' }
];

class Item extends React.PureComponent {

    render() {
        return (
            <i onClick={this.handleClick}>
                Component template for item {this.props.text}.
            </i>
        );
    }
}

ReactDOM.render(
    <List items={items} itemComponent={Item} />,
    document.getElementById('root')
);

Note: You cannot use the key prop in template components because it is a special React prop. Use dxkey instead.

Use the render property to specify a rendering function for a widget with template option:

import React from 'react';
import ReactDOM from 'react-dom';

import { Button } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

class CounterButton extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            counter: 0
        };

        this.handleClick = this.handleClick.bind(this);
    }

    render() {
        return (
            <Button
                text={this.props.text}
                render={(btn) => <div style={{ padding: 20 }}>{btn.text} (<b>{this.state.counter}</b>)</div>}
                onClick={this.handleClick}
            />
        );
    }

    handleClick() {
        this.setState({
            counter: this.state.counter + 1
        });
    }
}

ReactDOM.render(
    <CounterButton text='Click me!' />,
    document.getElementById('root')
);

The components that displays content in an overlaying window (for example, ScrollView), allow to specify the content as component children:

import React from 'react';
import ReactDOM from 'react-dom';

import { Button, ScrollView } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

class Example extends React.Component {

    render() {
        return (
            <ScrollView height={200} width={200}>
                <Button text='Show alert' onClick={() => alert('shown')} />
                <br />
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sed lacus
                    egestas, facilisis urna nec, fringilla nibh. Maecenas enim felis, ultricies
                    pretium aliquet ut, aliquam id urna. Lorem ipsum dolor sit amet, consectetur
                    adipiscing elit. Nam viverra est at neque fringilla, non iaculis magna
                    ultrices. Nunc posuere tincidunt elit a molestie. Nulla aliquet metus ex. Nunc
                    aliquam volutpat libero, ac tincidunt felis consectetur id. Sed diam lectus,
                    dictum non tempus fringilla, semper in dui. Donec at hendrerit massa. Aenean
                    quis suscipit nisi. Cras sed eros tristique, venenatis diam in, rhoncus enim.
                </p>
                <p>
                    Orci varius natoque penatibus et magnis dis parturient montes, nascetur
                    ridiculus mus. Curabitur et ex sit amet odio efficitur fermentum.
                    Donec lobortis hendrerit massa. Praesent tempus cursus tempus. Maecenas at
                    dolor lacus. Vestibulum suscipit ac mi vitae posuere. Maecenas id urna eget
                    sapien volutpat laoreet. Sed nulla purus, aliquam nec augue vel, consequat
                    tincidunt erat. Phasellus hendrerit rhoncus erat, ut fermentum orci molestie a.
                </p>
            </ScrollView>
        );
    }
}

ReactDOM.render(
    <Example />,
    document.getElementById('root')
);

DevExtreme Validation

DevExtreme React editors support built-in data validation.

import React from 'react';
import ReactDOM from 'react-dom';

import { Button, TextBox, ValidationGroup, ValidationSummary, Validator } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

class Example extends React.Component {

    validationRules = {
        email: [
            { type: 'required', message: 'Email is required.' },
            { type: 'email', message: 'Email is invalid.' }
        ],
        password: [
            { type: 'required', message: 'Password is required.' }
        ]
    };

    constructor(props) {
        super(props);

        this.validate = this.validate.bind(this);
    }

    render() {
        return (
            <ValidationGroup>
                <TextBox defaultValue={'email@mail.com'}>
                    <Validator validationRules={this.validationRules.email} />
                </TextBox>
                <TextBox defaultValue={'password'}>
                    <Validator validationRules={this.validationRules.password} />
                </TextBox>
                <ValidationSummary />
                <Button
                    text={'Submit'}
                    onClick={this.validate}
                />
            </ValidationGroup>
        );
    }

    validate(params) {
        const result = params.validationGroup.validate();
        if (result.isValid) {
            // form data is valid
            //params.validationGroup.reset();
        }
    }
}
ReactDOM.render(
    <Example />,
    document.getElementById('root')
);

Working with Data

DevExtreme includes the data layer that enables you to read and write data stored in different data sources.

The example below demonstrates how to use a DataSource with DevExtreme Components.

import React from 'react';
import ReactDOM from 'react-dom';

import DataSource from 'devextreme/data/data_source';
import { List } from 'devextreme-react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.compact.css';

const items = [
    { text: '123' },
    { text: '234' },
    { text: '567' }
];

class Example extends React.Component {

    constructor(props) {
        super(props);

        this.dataSource = new DataSource({
            store: {
                type: 'array',
                data: items
            },
            sort: [
                { getter: 'text', desc: true }
            ],
            pageSize: 1
        });
    }

    render() {
        return (
            <List dataSource={this.dataSource} />
        );
    }

    componentWillUnmount() {
        this.dataSource.dispose();
    }
}

ReactDOM.render(
    <Example />,
    document.getElementById('root')
);

Note that a DataSource is considered as a 'service'. So, modifying its properties does not cause component rerendering.

Typescript Support

We provide TypeScript declarations for DevExtreme Components. Strict typing allows you to catch many bugs and improve your workflow by adding features like auto-completion and automated refactoring.

Below is an example of appearance customization using TypeScript:

import * as React from "react";
import * as ReactDOM from "react-dom";
import { List } from "devextreme-react";

import "devextreme/dist/css/dx.common.css";
import "devextreme/dist/css/dx.light.compact.css";

interface IListItemProps {
    text: string;
}

class Item extends React.Component<IListItemProps, { counter: number }> {

    constructor(props: IListItemProps) {
        super(props);
        this.state = {
            counter: 0
        };

        this.handleClick = this.handleClick.bind(this);
    }

    public render() {
        return (
            <i onClick={this.handleClick}>
                Component template for item {this.props.text}. <b>Clicks: {this.state.counter}</b>
            </i>
        );
    }

    private handleClick() {
        this.setState({
            counter: this.state.counter + 1
        });
    }
}

const items: IListItemProps[] = [
    { text: "123" },
    { text: "234" },
    { text: "567" }
];

ReactDOM.render(
    <List items={items} itemComponent={Item} />,
    document.getElementById("root")
);

License

DevExtreme React components are released as an MIT-licensed (free and open-source) add-on to DevExtreme.

Familiarize yourself with the DevExtreme License.

A free trial is available!

Support & Feedback

23.1.9

2 months ago

23.2.5

2 months ago

22.1.13

3 months ago

22.2.11

3 months ago

23.1.8

3 months ago

23.2.4

3 months ago

22.1.12

5 months ago

23.1.7

5 months ago

22.2.10

5 months ago

21.2.15

5 months ago

23.2.3

5 months ago

22.1.11

8 months ago

23.2.2-beta

6 months ago

22.2.9

7 months ago

22.2.8

8 months ago

23.1.5

8 months ago

23.1.4

10 months ago

23.1.6

7 months ago

22.1.10

10 months ago

22.2.7

10 months ago

21.2.14

10 months ago

23.1.3

11 months ago

23.1.2-beta

11 months ago

23.1.2-beta.2

11 months ago

22.1.9

1 year ago

22.2.6

1 year ago

20.1.17

1 year ago

20.2.13

1 year ago

21.2.13

1 year ago

21.1.12

1 year ago

22.2.5

1 year ago

22.1.8

1 year ago

22.1.7

1 year ago

22.2.4

1 year ago

22.2.3

1 year ago

21.2.12

1 year ago

20.1.16

2 years ago

22.2.2-beta

1 year ago

22.1.6

2 years ago

19.1.16

2 years ago

21.2.11

2 years ago

19.2.15

2 years ago

18.2.18

2 years ago

21.1.11

2 years ago

20.2.12

2 years ago

22.1.5

2 years ago

21.2.10

2 years ago

21.2.9

2 years ago

22.1.4

2 years ago

22.1.3

2 years ago

21.1.10

2 years ago

21.2.8

2 years ago

22.1.2-beta

2 years ago

20.1.15

2 years ago

21.1.9

2 years ago

21.2.7

2 years ago

19.1.15

2 years ago

19.2.14

2 years ago

18.2.17

2 years ago

20.2.11

2 years ago

21.2.6

2 years ago

20.1.14

2 years ago

21.1.8

2 years ago

21.1.7

2 years ago

21.2.4

2 years ago

21.2.5

2 years ago

19.1.14

2 years ago

19.2.13

2 years ago

18.2.16

2 years ago

20.2.10

2 years ago

21.2.3

3 years ago

21.2.2-beta

3 years ago

21.1.6

3 years ago

20.2.9

3 years ago

21.1.5

3 years ago

20.1.13

3 years ago

20.2.8

3 years ago

21.1.4

3 years ago

21.1.3

3 years ago

20.1.12

3 years ago

20.2.7

3 years ago

19.1.13

3 years ago

19.2.12

3 years ago

18.2.15

3 years ago

21.1.2-beta

3 years ago

20.1.11

3 years ago

20.2.6

3 years ago

20.1.10

3 years ago

20.2.5

3 years ago

19.2.11

3 years ago

20.2.4

3 years ago

20.1.9

3 years ago

20.2.3

4 years ago

20.1.8

4 years ago

19.2.10

4 years ago

19.1.12

4 years ago

18.2.14

4 years ago

20.2.2-beta

4 years ago

20.1.7

4 years ago

20.1.6

4 years ago

20.1.5

4 years ago

19.2.9

4 years ago

20.1.4

4 years ago

18.2.13

4 years ago

19.2.8

4 years ago

19.1.11

4 years ago

20.1.3

4 years ago

20.1.2-beta

4 years ago

19.1.10

4 years ago

18.2.12

4 years ago

19.2.7

4 years ago

19.2.6

4 years ago

19.1.9

4 years ago

19.2.5

4 years ago

19.2.4

4 years ago

19.1.8

4 years ago

18.2.11

4 years ago

19.2.3

5 years ago

19.1.7

5 years ago

19.2.2-beta

5 years ago

19.1.6

5 years ago

18.2.10

5 years ago

19.1.5

5 years ago

19.1.4

5 years ago

18.2.9

5 years ago

18.2.9-pre-19149

5 years ago

19.1.3

5 years ago

18.2.9-pre-19135

5 years ago

18.2.9-pre-19128

5 years ago

18.2.8

5 years ago

19.1.2-beta

5 years ago

18.2.8-pre-19107

5 years ago

18.2.8-pre-19091

5 years ago

18.2.8-pre-19081

5 years ago

18.2.8-pre-19080

5 years ago

18.2.8-pre-19082

5 years ago

18.2.7

5 years ago

18.2.6

5 years ago

18.2.5

5 years ago

18.2.4

5 years ago

18.2.4-beta.1

5 years ago

18.2.3

5 years ago

18.2.2-beta.1

6 years ago

18.1.7-alpha.12

6 years ago

18.2.1-alpha.2

6 years ago

18.1.6-alpha.11

6 years ago

18.1.5-alpha.10

6 years ago

18.2.1-alpha.1

6 years ago

18.1.5-alpha.9

6 years ago

18.1.4-alpha.8

6 years ago

18.1.4-alpha.7

6 years ago

18.1.3-alpha.6

6 years ago

18.1.2-alpha.5

6 years ago

18.1.1-alpha.4

6 years ago

18.1.1-alpha.3

6 years ago

18.1.1-alpha.2

6 years ago

18.1.1-alpha.1

6 years ago