在组件之间共享道具定义或创建模型

时间:2018-01-29 14:48:01

标签: reactjs

我在组件之间创建了一些特定的模型,我想到了两种方法,一种是使用类定义创建的特定模型,另一种是基于共享组件的propTypes定义。

我创建了两个带有示例的沙箱,但是当组件收到多个道具或更深的对象时,无法确定最具可伸缩性的沙箱。

使用proptypes定义在组件之间共享道具定义的示例: https://codesandbox.io/s/n7p40xlo6j

// FirstComponent.js
export const propTypes = {
  user: PropTypes.shape({
    username: PropTypes.string,
    email: PropTypes.string,
  }),
};
const FirstComp = ({ user }) => (
    <div>
        <h2>First component</h2>
        <span>Username: {user.username}</span>
        <span> - </span>
        <span>Email: {user.email}</span>
    </div>
);
FirstComp.propTypes = {
    ...propTypes,
};
export default FirstComp;

// SecondComponent.js
import { propTypes } from './FirstComponent';
const SecondComp = ({ user }) => (
    <div>
        <h2>Second component</h2>
        <span>Email: {user.email}</span>
        <span> + </span>
        <span>Username: {user.username}</span>
    </div>
);
SecondComp.propTypes = { ...propTypes };
export default SecondComp;

// index.js
import FirstComponent from './FirstComponent';
import SecondComponent from './SecondComponent';
const [user1, user2] = [
    { username: 'user1', email: 'user1@default' },
    new User('user2', 'user2@default'),
];
const App = () => (
    <div>
        <FirstComponent user={user1} />
        <SecondComponent user={user2} />
    </div>
);

使用模型在组件之间共享道具定义的示例: https://codesandbox.io/s/jp08k5oqzw

// userModel.js
class User {
    constructor(username, email) {
        this.username = username;
        this.email = email;
    }
}
export default User;

// FirstComponent.js
import UserModel from './userModel.js';
const FirstComp = ({ user }) => (
    <div>
        <h2>First component</h2>
        <span>Username: {user.username}</span>
        <span> - </span>
        <span>Email: {user.email}</span>
    </div>
);
FirstComp.propTypes = {
    user: PropTypes.shape(UserModel),
};
export default FirstComp;

// SecondComponent.js
import UserModel from './userModel.js';
const SecondComp = ({ user }) => (
    <div>
        <h2>Second component</h2>
        <span>Email: {user.email}</span>
        <span> + </span>
        <span>Username: {user.username}</span>
    </div>
);
SecondComp.propTypes = {
    user: PropTypes.shape(UserModel),
};
export default SecondComp;

// index.js
import User from './userModel.js';
import FirstComponent from './FirstComponent.js';
import SecondComponent from './SecondComponent.js';
const [user1, user2] = [
    { username: 'user1', email: 'user1@default' },
    new User('user2', 'user2@default'),
];
const App = () => (
    <div>
        <FirstComponent user={user1} />
        <SecondComponent user={user2} />
    </div>
);

1 个答案:

答案 0 :(得分:0)

不错的实验。我不认为有一个答案,就像大多数事情一样,它取决于你想要的代码和你的“可扩展”的含义

带有“普通对象”的第一个选项适用于您希望能够使用共享定义作为默认值进行dinamically更改或扩展proptypes的情况,即:

const propTypes = {
  user: PropTypes.shape({
    username: PropTypes.string,
    email: PropTypes.string,
  }),
};

const FirstComp = ({ user }) => (
  <div>
    <h2>First component</h2>
    <span>Username: {user.username}</span>
    <span> - </span>
    <span>Email: {user.email}</span>
  </div>
);
FirstComp.propTypes = {
  ...propTypes,
};

const SecondComp = ({ user }) => (
  <div>
    <h2>Second component</h2>
    <span>Email: {user.email}</span>
    <span> + </span>
    <span>Username: {user.username}</span>
  </div>
);
// Not a particularly good example, but it illustrates my point
SecondComp.propTypes = { ...propTypes, email: PropTypes.shape({something}) };

这是一个有趣的选择,如果你正在构建一套类似的组件,它们会以不同的方式处理某些propType。

第二种选择对于模型的使用更加一致,在我看来,在这种特殊情况下用户模型更适合。它是从组件和React的API中抽象出来的,这很好,因为这个特定的模型不需要知道UI逻辑,你可以稍后通过提供不同的序列化选项来提高它,通过HTTP请求发送它而不用担心跨多个组件的对象形状不一致,得到一种“类型安全”