javascript - ReactJS - 在 sibling 之间传递引用

标签 javascript reactjs recursion tree siblings

我目前在构建 ReactJS 应用程序时遇到问题。我有一个采用这种形式的数组:

[{
   _id: 123456,
   ...
   children: [
      {
         _id: 568,
         ...
         children: [...] // and so on, recursively
      },
      ....
   ]
}]

该架构需要呈现为某种“进化树”,如下所示:

| item | => | item's first child  | => | first child's first child | ..
|      | => | item's second child |

其中每个“item”或“child”都是一个组件(称为EvolutionStep),每个“=>”箭头是另一个组件(称为EvolutionArrow)。所以我们有三个组成部分:

Evolution Chain => parent component, that renders
Evolution Step => containing the evolution props (name, etc)
Evolution Arrow => linking one step to one of it's children. 

进化箭头需要指向渲染下一个进化步骤的方向(在示例中,项目和项目的第一个子项之间的第一个箭头将指向直线,但如果项目的第一个子项的位置类似于 {顶部:-20px} 箭头应稍微向上。

为了实现这一点,每个进化步骤在渲染时都会调用进化链中的函数以将其引用添加到本地状态。每个进化箭头在渲染时都会传递对其应指向的进化步骤的引用。问题是 Evolution Arrow 的 reference 属性始终未定义...

我不知道我的解释是否正确,所以这是我的代码。请注意,如果在 Evolution Arrow 类中放置 console.log(this.props.references),它始终是未定义的。

预先感谢您的帮助!

import PropTypes from 'prop-types';
import React from 'react';

class EvolutionStep extends React.Component {

    componentDidMount() {
        this.props.mountCallable(this.props.step._id, this);
    }

    render() {
        return (
            <div style={{width: this.props.width + "%"}} data-identifier={this.props.step._id}>step</div>
        );
    };

}

class EvolutionArrow extends React.Component {

    render() {
        console.log(this.props);
        return (
            <div>arrow</div>
        );
    }
}

const EvolutionChain = class EvolutionChain extends React.Component {

    constructor(props) {
        super(props);

        this.processStack.bind(this);
        this.stepDidMount.bind(this);
        this.preRender.bind(this);

        this.state = {
            cols: 0,
            chainData: [],
            refs: {}
        };
    }

    componentDidMount() {
        this.processStack();
    }

    stepDidMount(step_id, element) {
        let refs = this.state.refs;

        if (undefined == typeof(refs[step_id])) {
            refs[step_id] = element;
            this.setState({refs: refs});
        }
    }

    processStack() {
        if (null == this.props.chain) {
            return null;
        }

        let stack = [this.props.chain.children[0]];
        let results = [];

        while (stack.length > 0) {
            const current = stack.pop();
            // build current element
            results.push({type: 'step', props: {step: current} });
//            results.push(<EvolutionStep key={current._id} ref={(step) => this.addRef(current._id, step)} step={current} width={(100 / this.state.cols)}/>);
            this.setState({cols: this.state.cols + 1});
            if (current.children.length > 0) {
                let arrows = [];
                current.children.map((item) => {
                    arrows.push({pointsTo: item._id});
                    //arrows.push(<EvolutionArrow pointsTo={item._id} references={this.state.refs}/>);
                });
//                results.push(<div className="arrow" width={(100 / this.state.cols)}>{arrows}</div>);
                results.push({type: 'arrows', arrows: arrows});
                this.setState({cols: this.state.cols + 1});
                stack = current.children;
            }
        }

        results.reverse();
        this.setState({chainData: results});
    }

    preRender() {
        var components = [];
        this.state.chainData.map((item) => {
            switch (item.type) {
                case 'step':
                    components.push(<EvolutionStep key={item.props.step._id} {...item.props} mountCallable={(step_id, elem) => this.stepDidMount(step_id, elem)}/>);
                    break;
                case 'arrows':
                    let arrows = [];
                    item.arrows.map((arrow) => {
                        arrows.push(<EvolutionArrow pointsTo={arrow.pointsTo} references={this.state.refs[arrow.pointsTo]} />);
                    });
                    components.push(<div className="arrow">{arrows}</div>);
                    break;
            }
        });

        return components;
    }

    render() {

        let toRender = this.preRender();
        return (
            <div className="container-fluid">
                {toRender}
            </div>
        );
    }

};

/** TODO: PropTypes **/

export default EvolutionChain;

最佳答案

修好了!我所要做的就是将 undefined 括在 stepDidMount 中的引号中,否则条件始终为 false...

关于javascript - ReactJS - 在 sibling 之间传递引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43754617/

相关文章:

java - 字母键盘问题,但使用字符串函数(Java)

java - 在 0/1 KnapSack 中打印结果(递归蛮力)

c++11 - 如何使这个函数尾递归?

javascript - Cheerio.js 没有抓取非内联样式?

javascript - 为什么我的 switch 语句不匹配任何大小写?

javascript - 在模态/覆盖 react 组件中使用React componentDidMount

reactjs - React 钩子(Hook)的依赖项是什么?

javascript - 防止在 Angular 中按 Enter 键时提交表单

javascript - 找不到 babel.config.json 中指定的模块

reactjs - 使用 Webpack 在 Electron 项目中使用外部目录中的组件