React.js - 使用来自不同级别的组件层次结构的

时间:2016-08-29 18:18:20

标签: javascript dom reactjs

我们需要在window.onresizewindow.onscroll上的组件层次结构的不同部分执行与DOM元素相关的一些操作:

1)调整大小到移动分辨率时移动元素

2)滚动时更改类和样式。

问题是元素处于React组件层次结构的不同级别,即嵌套在不同的组件中。因此,如果我理解正确,我就无法使用refs来访问DOM节点。

我有: {someCondition ? <FirstComponent/>: <SecondComponent/>}

someCondition可以由于用户UI操作而改变,或者从页面加载开始就可以改变。

我已经尝试在我的componentDidMount上使用componentDidUpdateFirstComponent,但发现componentDidMount仅在someCondition从一开始就为真时触发,componentDidUpdate确实在someCondition发生更改时触发,但此时所需的DOM元素(包含在组件中)尚未就绪,document.getElementById失败。

添加window.requestAnimationFrame没有帮助。

我想在React中应该有一个可行的方法吗?

也许React.findDomNode

谢谢。

1 个答案:

答案 0 :(得分:4)

你所描述的是React的对立面。这是我在使用基于命令式jQuery / Dojo的框架时所期望的方法。

使用React,您正在开发知道如何将状态转换为呈现HTML的功能组件,并且您需要以不同方式处理问题。

对于您的问题,您的window.onresizewindow.onscroll回调应该尝试操纵React DOM元素。相反,它应该只更新状态并让React重新渲染。您的React组件应该接收此状态并相应地进行渲染。

这是一个简单的示例,其中主应用程序侦听这些事件并更新其状态,从而触发重新呈现。该应用程序将状态作为道具传递给孩子们。孩子们使用道具有条件地改变他们的css类名。他们也可以轻松渲染不同的html或内联样式。

const Component2 = ({someCondition2}) => {
    const className = someCondition2 ? "foo" : "bar";
    return <div className={className}>Hello</div>;
};

const Component1 = ({someCondition1, someCondition2}) => {
    const className = someCondition1 ? "A" : "B";
    return (
        <div className={className}>
            <Component2 someCondition2={someCondition2} />
        </div>
    );
};

class App extends React.Component {
    state = {
        someCondition: false,
        someCondition2: true,
    };

    componentDidMount() {
        window.onresize = ev => {
            const someCondition = ev.xxx;
            // re-render with the new state
            this.setState({ someCondition });
        };

        window.onscroll = ev => {
            const someCondition2 = ev.xxx;
            this.setState({ someCondition2 });
        };
    }

    render() {
        const {someCondition, someCondition2} = this.state;
        return (
           <Component1
              someCondition1={someCondition1}
              someCondition2={someCondition2} />
        );
    }
}

React.render(<App />, document.getElementById("container"));