defaultProps中的随机数据

时间:2016-06-14 18:03:57

标签: javascript reactjs

我使用React已经很长时间了,我遇到了一个有趣的问题:基本上,我想使用defaultProps作为 fallbackProps - 这就是他们的意思是的,但有一个难点 - 来自无状态/ defaultProps API的class extend Component属性和来自getDefaultProps() API的缓存React.createClass都是不可变的(和常量)。

示例:

var ExampleComponent = React.createClass({
    getDefaultProps: function () {
        return {
            number: Math.random()
        };
    }
    // ...
});

// or equivalent with ES6 classes

class ExampleComponent extends React.Component {
    // ...
}

ExampleComponent.defaultProps = {
    number: Math.random()
};

// then...

<main>
    <ExampleComponent />            // cached random
    <ExampleComponent />            // cached random
    <ExampleComponent number={1} /> // 1
    <ExampleComponent />            // cached random
    <ExampleComponent />            // cached random
</main>

问题是,我希望动态 defaultProps - 为每个组件实例分开。

示例:

<main>
    <ExampleComponent />            // fresh random
    <ExampleComponent />            // fresh random
    <ExampleComponent number={1} /> // 1
    <ExampleComponent />            // fresh random
    <ExampleComponent />            // fresh random
</main>

我知道,使用stategetInitialState 每个组件)很容易实现这种行为,但我想知道是否有可能没有状态和没有HOC或类似方法。

2 个答案:

答案 0 :(得分:4)

是。这可以通过使用ES5 getter来定义defaultProps对象:

ExampleComponent.defaultProps = Object.create({}, {
  number: {
    enumerable: true,
    get: () => Math.random()
  }
});

Demo

正如您所注意到的,defaultProps是一个静态成员,因此每个类只会初始化一次。但是,当调用React.createElement时,它会通过枚举所有属性并将它们复制到一个新的空白对象来创建defaultProps的新副本(此枚举是enumerable: true必须的原因在描述符中设置)。 Relevant part of React's source

  // Resolve default props
  if (type && type.defaultProps) {
    var defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }

defaultProps[propName]调用getter,它会生成一个新的随机数,然后存储在props中。

答案 1 :(得分:0)

我的模态需要一个随机的“唯一”ID,这就是我执行以下操作的原因:

const Modal = () => { // my component
    const id = useMemo(() => {
        // this will be run only once on "mount"
        return `modal-${randomNumber(1111,9999)}`;
    }, []); // empty array is important!

    return <div id={id}>Model {id}</div>;
};

/**
 * Random number between min (including) and max (excluding)
 * @param {number} min
 * @param {number} max
 * @return {number}
 */
const randomNumber = (min, max) => {
    return Math.floor(
        (Math.random() * (max - min)) + min
    );
};

这是您问题的一种解决方案,只是它不使用 defaultProps。另一方面,它不会在每次重新渲染时为您提供随机 ID,例如 @quw 解决方案。 也许它对某些人有用。

Demo