动态将道具应用于组件

时间:2018-08-10 21:57:55

标签: reactjs

我正在循环渲染组件。我想将它们随机放置在屏幕上,所以我考虑使用一个函数来渲染它们。该函数应注意寻找随机的x,y坐标并将其应用于渲染的组件。但是我该怎么做?

App.js

class App extends Component {
  // the shapes are SFC returning `<svg>` element
  state = {
    shapes: [<Circle />, <Square />, <Star />, <Hexa />, <Penta />]
  };

  randomShapeIndex = correctShapeIndex => {
    const max = this.state.shapes.length - 1;
    return Math.floor(Math.random() * (max + 1));
  };

  render() {
    const { shapes } = this.state;

    const selectedShapes = [];
    const numberOfShapes = 5;
    let randomIndex;
    for (let i = 0; i < numberOfShapes; i++) {
      randomIndex = this.randomShapeIndex();
      selectedShapes.push(shapes[randomIndex]);
    }

    return (
      <div className="App">
        {incorrectShapes.map((shape, index) =>
          this.positionElementRandomly(
            <Element key={index} correct={false} shape={shape} />
          )
        )}
      </div>
    );
  }

  // this is the function I want to create x,y coordinates and apply to Element as props `x` and `y`
  positionElementRandomly = element => {
    element = { ...element };
    return element;
  };
}

export default App;

Element.js

import React, { Component } from "react";

class Element extends Component {
  render() {
    const { shape, x, y } = this.props;
    return (
      <div
        style={{ position: "absolute", left: x, top: y }}
      >
        {shape}
      </div>
    );
  }
}

export default Element;

2 个答案:

答案 0 :(得分:1)

这是您的功能: https://reactjs.org/docs/react-api.html#cloneelement

positionElementRandomly = element => {
  const randomPositionedElement = React.cloneElement(element, {x: 1, y: 2});
  return randomPositionedElement;
};

另一方面-最好将shape逻辑与定位分开。

类似这样的东西:

positionElementRandomly = element => {
  const randomPositionedElement = React.cloneElement(element, {x: 1, y: 2});
  return (<PositionWrapper x={1} y={2}>{element}</PositionWrapper>);
}; 

Element.js

import React, { Component } from "react";

class Element extends Component {
  render() {
    const { shape, x, y } = this.props;
    return (
      <div>
        {shape}
      </div>
    );
  }
}

export default Element;

PositionWrapper.js

import React, { Component } from "react";

class PositionWrapper extends Component {
  render() {
    const { children, x, y } = this.props;
    return (
      <div
        style={{ position: "absolute", left: x, top: y }}
      >
        {children}
      </div>
    );
  }
}

export default PositionWrapper;

它可能需要额外的div,但会导致架构更简洁。

答案 1 :(得分:0)

这是您可以做的。使用React CloneElement并为每个元素生成一个新实例。

class App extends React.Component {
  // the shapes are SFC returning `<svg>` element
  constructor(props) {
    super(props);
    this.state = {
      shapes: [<Circle />, <Square />, <Circle />, <Square />]
    };
  }

  randomShapeIndex = correctShapeIndex => {
    const max = 10;
    return Math.floor(Math.random() * (max + 1));
  };

  render() {
    const { shapes } = this.state;

    const selectedShapes = [];
    const numberOfShapes = 5;
    let randomIndex;
    for (let i = 0; i < numberOfShapes; i++) {
      randomIndex = this.randomShapeIndex();
      selectedShapes.push(shapes[randomIndex]);
    }

    return (
      <div className="App">
        {" "}
        {shapes.map((shape, index) =>
          this.positionElementRandomly(
            <Element
              key={index}
              correct={false}
              shape={shape}
              x={Math.random(10) * 100}
              y={Math.random(10) * 100}
            />
          )
        )}{" "}
      </div>
    );
  }

  // this is the function I want to create x,y coordinates and apply to Element as props `x` and `y`
  positionElementRandomly = element => {
    return React.cloneElement(element);
  };
}

class Element extends React.Component {
  render() {
    const { shape, x, y } = this.props;
    return (
      <div
        style={{
          position: "absolute",
          left: x,
          top: y
        }}
      >
        {shape}{" "}
      </div>
    );
  }
}
class Circle extends React.Component {
  render() {
    return <div> Circle </div>;
  }
}

class Square extends React.Component {
  render() {
    return <div> Square </div>;
  }
}

ReactDOM.render(<App />, document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
</div>