React组件应该在状态或道具上使用(固定)值吗?

时间:2019-07-31 00:38:53

标签: reactjs

我是React的新手,试图了解我在做什么是否是反模式。我有一个呈现包含<select>输入的模式的组件。 <select>中可用的选项来自服务-它们可能永远不会改变,但是我希望这些值不能存在于服务中,而不能在组件UI上进行硬编码。我很想将此选项数组分配给this而不是this.state,因为它不会改变。我可以通过props分配选项,但这似乎是在要求父组件做太多事情-它不必知道这些值。

所以基本问题是,在React中将某些数据直接存储在this上而不是在状态或道具上是否合法?

2 个答案:

答案 0 :(得分:2)

有很多方法可以处理您的情况,这在React开发中很常见。我认为,具有固定值的数据(不会随时间变化,例如:日期格式,某些选择选项(性别)等)应更好地存储在应用程序中的某个位置,以便可以更好地管理和维护(同样,这将从组件中的呈现逻辑中删除常量值)。我始终保持组件文件中常量/固定值(将它们移至constants.js中)和函数(将它们移至utils/文件夹中并进行单元测试)的清洁,以便它们可以易于阅读和维护。

希望以下信息可以为您提供帮助:

// Storing them into one single file
import { services } from '../constants';

// Global constants - when you're pretty sure it will never change;
// using global constants also make it easier to update from the top of the component file.
const SERVICES = [
  'services-a',
  'services-b',
];

// Storing in redux store
@connect(state => ({ services: state.services }))
export default class App extends PureComponent {
  static propTypes = {
    services: PropTypes.array.isRequired,
  }

  // Using the getter method; I mainly use this when I want to process some information with props data
  // NOTE: Some people might think that this is an anti-pattern in React
  get services() {
    const { someRelevantDetailsFromProps } = this.props;
    // process and return
    return someRelevantDetailsFromProps.map();
  }

  render() {
    return (
      <select>
        {/* Importing from constant file */}
        { services.map(service => <option value={service}>{service}</option>) }

        {/* Using class getter method */}
        { this.services.map(service => <option value={service}>{service}</option>) }

        {/* Using redux store */}
        { this.props.services.map(service => <option value={service}>{service}</option>) }

        {/* Using global contant */}
        { SERVICES.map(service => <option value={service}>{service}</option>) }
      </select>
    );
  }
}

答案 1 :(得分:0)

当然,您可以将自己的变量存储在类中,即使它们不会按状态更新。没有反模式。

大多数反模式和有关反模式的文章都是为了避免出现未知的问题和副作用。但是,如果您真的知道React的工作原理,那么您可以根据需要进行游戏。我认为使用自己的方式可能会遇到很多问题,但这是最好的学习方式。我的意思是,不要阻挡自己失去创造力。您已经在寻找正确的方法了。

每个反模式也具有真实模式。因此,您总是有机会。一个例子;从父组件获取“ prop值”以在构造函数中放置“初始状态”是反模式的。因为它永远不会更新。但是,如果您使用getDerivedStateFromProps生命周期方法从props更新新的状态值,那么它将不是反模式。

我多次使用该逻辑来避免未安装的组件按状态呈现:

updateState()
{
  // To avoid unmounted setState for unfinished process
  if (this.mounted)
  {
    this.setState(...);
  }
}

人们已经喜欢 React ,因为它只是Javascript,即使它具有JSX。

class MyComponent extends React.Component
{
  static getDerivedStateFromProps(props, state)
  {
    // We always getting actual state when parent change the prop value
    // Now it became true pattern with keep up-to-date the state from props
    if (props.defaultSelectValue !== state.selectValue)
    {
      return {
        selectValue: props.defaultSelectValue,
      };
    }
    return null;
  }

  constructor(props)
  {
    super(props);

    const { defaultSelectValue } = this.props;

    this.state =
    {
      selectValue: defaultSelectValue,
    };

    this.cache =
    {
      SelectComponent: ({ items }) => // We used arrow function to don't lose the this scope
      {
        const { selectValue } = this.state; // this will be always actual state

        return (
         <select value={selectValue}>
           <option value="0">Yes</option>
           <option value="1">No</option>
         </select>
        );
      },
    };
  }

  render()
  {
    const { SelectComponent } = this.cache;

    return (
     <SelectComponent />
    );
  }
}

因此,如果您知道自己在做什么,那么就没有反模式了。