V
V
Vladimir Golub2019-06-07 14:58:42
React
Vladimir Golub, 2019-06-07 14:58:42

How to get ref width and height?

At the moment I'm doing it like this:

import React, { Component } from 'react';

import ReactDOM from 'react-dom';

import './testMenu.css';

class testMenu extends Component {

    constructor(props) {
        super(props);

        this.state = {
            menu: [
                {
                    title: 'Пункт 1',
                    active: true
                },
                {
                    title: 'Пункт 2',
                    active: false
                },
                {
                    title: 'Пункт 3',
                    active: false
                }
            ]
        };

        this._menuItems = [];
        this._menuBlock = null;
    }

    shouldComponentUpdate(nextProps, nextState, nextContext) {
        if (this.state.menu != nextState.menu) {
            return true;
        }

        return false;
    }

    componentDidMount() {
        this.getStyleMenuBlock();
    }

    handlerClickItem = (indexClick) => {
        let menuItems = this.state.menu.slice();

        menuItems.map((item, indexItem) => {
            if (indexItem == indexClick) {
                item.active = true;
            } else {
                item.active = false;
            }
        });

        this.setState({
            menu: menuItems
        })
    };

    getStyleMenuBlock = () => {
        let menuItems = this.state.menu.slice(),
            activeIndex = 0;

        menuItems.map((item, index) => {
            if (item.active) {
                activeIndex = index;
            }
        });


        this._menuBlock.style.width = ReactDOM.findDOMNode(this._menuItems[activeIndex]).getBoundingClientRect().width + 'px';
        this._menuBlock.style.height = ReactDOM.findDOMNode(this._menuItems[activeIndex]).getBoundingClientRect().height + 'px';
    };

    render() {
        return (
            <div className='test-menu'>
                <ul className='test-menu__menu'>
                    <React.Fragment>
                        {
                            this.state.menu.map((item, index) =>
                                <li
                                    className={`test-menu__item ${ item.active ? 'test-menu__item_active' : '' }`}
                                    onClick={ () => this.handlerClickItem(index) }
                                    ref={ref => { this._menuItems[index] = ref; return true; }}
                                >{ item.title }</li>
                            )
                        }
                        <li
                            className='test-menu__block'
                            ref={ref => { this._menuBlock = ref }}
                        />
                    </React.Fragment>
                </ul>
            </div>
        )
    }
}
export default testMenu;

How can I get it directly in render ?
getStyleMenuBlock = () => {
        let menuItems = this.state.menu.slice(),
            ativeIndex = 0;

        menuItems.map((item, index) => {
            if (item.active) {
                ativeIndex = index;
            }
        });

        return {
            height: ? (this._menuItems[activeIndex].?)
            width: ? (this._menuItems[activeIndex].?)
        }
    };

    render() {
        return (
            <div className='test-block'>
                <ul className='test-block__menu'>
                    <React.Fragment>
                        {
                            this.state.menu.map((item, index) =>
                                <li
                                    className={`test-block__item ${ item.active ? 'test-menu__item_active' : '' }`}
                                    onClick={ () => this.handlerClickItem(index) }
                                    ref={ref => { this._menuItems[index] = ref; return true; }}
                                >{ item.title }</li>
                            )
                        }
                        <li className='test-block__block' style={ this.getStyleMenuBlock() }></li>
                    </React.Fragment>
                </ul>
            </div>
        )
    }

In the last option tried getBoundingClientRect().width doesn't work, clientHeight doesn't work.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Anton Spirin, 2019-06-07
@RazerVG

How can I get it directly in render ?

You can't do that. At the time of the first call to render, the target elements have not yet been mounted.
What do you even want to do? Perhaps the problem can be solved in a more elegant way.

H
hzzzzl, 2019-06-07
@hzzzzl

getStyleMenuBlock = () => {

что делает this.state.menu.slice() , если this.state.menu это уже массив?

        let menuItems = this.state.menu.slice(),
            ativeIndex = 0;

        menuItems.map((item, index) => {
            if (item.active) {
                ativeIndex = index;
            }
        });

***

ativeIndex / activeIndex ?
если это опечатка, то в этом моменте кода вообще что-то есть в this._menuItems[activeIndex] , или undefined ?

***

        return {
            height: ? (this._menuItems[activeIndex].?)
            width: ? (this._menuItems[activeIndex].?)
        }
    };

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question