В чем разница между состоянием и реквизитом в React?

Я смотрел курс Pluralsight на React, и инструктор заявил, что реквизит не должен быть изменен. Я сейчас читаю статья (uberVU / react-guide) на реквизит против государства, и он говорит

и реквизит, и изменения состояния запускают обновление рендеринга.

далее в статье говорится:

Props (сокращение от properties) - это конфигурация компонента, его параметры, если можно. Они получены свыше и неизменный.

  • таким образом, реквизит может меняться, но они должны быть неизменными?
  • когда следует использовать реквизит и когда следует использовать состояние?
  • если у вас есть данные, необходимые компоненту React, он должен быть передан через props или setup в компоненте React через getInitialState?

20 ответов


реквизит и состояние связаны. Состояние одного компонента часто становится реквизитом дочернего компонента. Реквизит передается дочернему элементу в методе рендеринга родителя в качестве второго аргумента React.createElement() или, если вы используете JSX, более знакомые атрибуты тегов.

<MyChild name={this.state.childsName} />

значение состояния Родителя childsName становится ребенка this.props.name. С точки зрения ребенка, имя prop является неизменным. Если его нужно изменить, родитель должен просто изменить его внутреннее состояние:

this.setState({ childsName: 'New name' });

и React будет распространять его на ребенка для вас. Естественный следующий вопрос: что, если ребенку нужно изменить свое имя? Обычно это делается через дочерние события и обратные вызовы родителей. Ребенок может предоставить событие с именем, например,onNameChanged. Затем родитель подпишется на событие, передав обработчик обратного вызова.

<MyChild name={this.state.childsName} onNameChanged={this.handleName} />

ребенок передаст запрошенное новое имя в качестве аргумента для обратного вызова события вызов, например,this.props.onNameChanged('New name'), и родитель будет использовать имя в обработчике событий для обновления своего состояния.

handleName: function(newName) {
   this.setState({ childsName: newName });
}

для связи родитель-ребенок, просто передать реквизит.

использовать государство для хранения данных, необходимых текущей странице, в представлении контроллера.

использовать реквизит для передачи данных и обработчиков событий в дочерние компоненты.

эти списки должны помочь вам при работе с данными в вашем компонентов.

реквизит

  • неизменны
    • что позволяет быстро реагировать проверка ссылок
  • используются для передачи данных вниз с вашего view-controller
    • ваш компонент верхнего уровня
  • иметь более высокую производительность
    • используйте это для передачи данных дочерним компонентам

государство

  • должно управляться в вашем view-controller
    • ваш топ-уровня компонент
  • изменчиво
  • имеет худшие показатели
  • не должен быть доступен из дочерних компонентов
    • передать его вниз с реквизитом вместо

для связи между двумя компонентами, которые не имеют отношения родитель-ребенок, вы можете настроить свое собственное глобальное событие система. Подпишитесь на события в componentDidMount (), отпишитесь в componentWillUnmount(), и вызовите setState () при получении события. Flux pattern-один из возможных способов организовать это. - https://facebook.github.io/react/tips/communicate-between-components.html

Какие Компоненты Должны Иметь Состояние?

большинство ваших компонентов должны просто взять некоторые данные из реквизита и делать его. Однако иногда вам нужно ответить на ввод пользователя, a запрос сервера или прохождение времени. Для этого вы используете государство.

постарайтесь сохранить как можно больше ваших компонентов . Поступая это вы изолируете состояние до его наиболее логичного места и минимизируете избыточности, что делает его легче рассуждать о вашем приложении.

общим шаблоном является создание нескольких компоненты, которые просто визуализация данных и наличие компонента с состоянием над ними в иерархии это передает свое состояние своим детям через реквизит. Динамическая фильтрация компонент инкапсулирует всю логику взаимодействия, в то время как компоненты без состояния заботятся о рендеринге данных декларативным способом. - https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#what-components-should-have-state

что должно идти в состоянии?

состояние должно содержать данные, которые могут изменяться обработчиками событий компонента чтобы запустить обновление пользовательского интерфейса. В реальных приложениях эти данные, как правило, очень маленький и JSON-сериализации. При создании компонента stateful подумайте о минимально возможное представление его состояния, и только хранить те свойства в этом.государство. Внутри render () просто вычислите любой другой информация, которая вам нужна, основана на этом состоянии. Ты найдешь это мышление. о и написание приложений таким образом, как правило, приводит к наиболее правильное применение, так как добавление избыточных или вычисленных значений к состояние означает, что вам нужно явно синхронизировать их, а не положитесь на React вычисляя их для вас. - https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#what-should-go-in-state


реквизит против резюме состояния мне больше всего нравится здесь:https://github.com/uberVU/react-guide/blob/master/props-vs-state.md Большая шляпа для этих парней. Ниже приведена отредактированная версия этой страницы:


реквизит против государства

tl; dr если компоненту необходимо изменить один из его атрибутов в какой-то момент времени, этот атрибут должен быть частью его состояния, иначе он должен быть просто опорой для этого Деталь.


реквизит

Props (сокращение от properties) - это конфигурация компонента. Они получены свыше и неизменны в том, что касается принимающего их компонента. Компонент не может изменять свои реквизиты, но он отвечает за объединение реквизитов своих дочерних компонентов. Реквизит не должен быть просто данными - функции обратного вызова могут передаваться как реквизит.

государство

государство-это структура данных, начинается со значения по умолчанию при монтировании компонента. Он может мутировать во времени, в основном в результате пользовательских событий.

компонент внутренне управляет собственным состоянием. Помимо установки начального состояния, он не имеет никакого дела с состоянием своих детей. Вы можете концептуализировать состояние как частное для этого компонента.

изменение реквизита и государства

                                                   props   state
    Can get initial value from parent Component?    Yes     Yes
    Can be changed by parent Component?             Yes     No
    Can set default values inside Component?*       Yes     Yes
    Can change inside Component?                    No      Yes
    Can set initial value for child Components?     Yes     Yes
    Can change in child Components?                 Yes     No
  • обратите внимание, что как реквизит, так и исходные значения состояния, полученные от родителей, переопределяют значения по умолчанию, определенные внутри компонента.

должен ли этот компонент иметь состояние?

государство является необязательным. Поскольку состояние увеличивает сложность и снижает предсказуемость, предпочтительнее компонент без состояния. Даже если вы явно не можете обойтись без состояния в интерактивном приложении, вы должны избегать слишком много компонентов с состоянием.

типы компонентов

Компонент только реквизит, нет состояния. Не так уж много. кроме функции render (). Их логика вращается вокруг реквизита, который они получают. Это делает их очень легкими для отслеживания и проверки.

Компонент Состояния как реквизит, так и состояние. Они используются, когда компонент должен сохранять некоторое состояние. Это хорошее место для связи клиент-сервер (XHR, веб-сокеты и т. д.), обработка данных и реагирование на пользовательские события. Такого рода логистика должна быть инкапсулирована в умеренное количество компонентов с состоянием, в то время как вся логика визуализации и форматирования должна двигаться вниз по течению во многие компоненты без состояния.

источник


большинство ответов сбивают с толку начинающих, а уточняют. Это очень трудно общайтесь и понимайте. вы можете понять это, связав его с равниной JS.

простыми словами,

государство относится к локальному состоянию компонента, которое не может быть доступно и изменено вне компонента и может использоваться и изменяться только внутри компонента.

равнина JS

const DummyFunction = () => {
  let name = 'Manoj';
  console.log(`Hey ${name}`)
}

реагировать JS эквивалент

class DummyComponent extends React.Component {
  state = {
    name: 'Manoj'
  }
  render() {
    return <div>Hello {this.state.name}</div>;
  }

реквизит, С другой стороны, сделайте компоненты многоразовыми, предоставив компонентам возможность получать данные от родительского компонента в виде реквизита.

простой JS

const DummyFunction = (name) => {
  console.log(`Hey ${name}`)
}
DummyFunction('Manoj');
DummyFunction('Ajay');

реагировать JS

class DummyComponent extends React.Component {
  render() {
    return <div>Hello {this.props.name}</div>;
  }

}
// when using the component
<DummyComponent name="Manoj" />
<DummyComponent name="Ajay" />

кредиты:https://medium.com/@manojsinghnegi

статьи Linke:https://medium.com/@manojsinghnegi/react-state-vs-props-explained-51beebd73b21


реквизит (сокращение от "свойства") и государство оба являются простыми JavaScript объекты. Пока оба держат информацию которая влияет на выход рендеринг, они отличаются одним важным способом: реквизит передается компонент (похожий на параметры функции), тогда как государство is управляется в компоненте (аналогично переменным, объявленным в функция.)

Так Просто государство ограничено к вашему текущему компоненту, но реквизит можно перейти к любому компоненту, который вы хотите... Вы можете пройти государство текущего компонента, как prop С другими компонентами...

также в React у нас есть компоненты без состояния которые имеют только реквизит, а не внутреннее состояние...

пример ниже показывает, как они работают в вашем приложении:

родитель (государство-полный компонент):

class SuperClock extends React.Component {

  constructor(props) {
    super(props);
    this.state = {name: "Alireza", date: new Date().toLocaleTimeString()};
  }

  render() {
    return (
      <div>
        <Clock name={this.state.name} date={this.state.date} />
      </div>
    );
  }
}

ребенок (компонент без состояния):

const Clock = ({name}, {date}) => (
    <div>
      <h1>{`Hi ${name}`}.</h1>
      <h2>{`It is ${date}`}.</h2>
    </div>
);

в основном, разница в том, что государство что-то вроде атрибутов в ООП : это что-то local к классу (компоненту), используемому для лучшего его описания. реквизит как параметры-они прошло компоненту от вызывающего компонента (родителя): как если бы вы вызывали функцию с определенными параметрами.


и государство и реквизит in react используются для управления данными в компоненте, обычно реквизит задается родителем и передается дочерним компонентам, и они фиксируются по всему компоненту. Для данные, которые будут меняться, мы должны использовать государство. И реквизитнеизменяемые в то время как состояния Мутабельный, Если вы хотите изменить реквизит, вы можете сделать из родительского компонента, а затем передать его дочерним компонентам.


реквизит : реквизит-это ничто иное свойство компонента и компонента реагируют лишь функцию JavaScript.

  class Welcome extends React.Component {
    render() {
      return <h1>Hello {this.props.name}</h1>;
    }
  }

const element =;

здесь <Welcome name="Sara" /> передача объекта {name: 'Sara'} в качестве реквизита компонента Welcome. Для передачи данных от одного родительского компонента к дочернему мы используем реквизит. Реквизит неизменен. Во время жизненного цикла компонента реквизит не должен меняться (считайте их неизменяемыми).

состояние: состояние доступно только внутри Деталь. Для отслеживания данных компонентов мы используем. мы можем изменить состояние setState. Если нужно передать состояние ребенку, мы должны передать его в качестве реквизита.

class Button extends React.Component {
  constructor() {
    super();
    this.state = {
      count: 0,
    };
  }

  updateCount() {
    this.setState((prevState, props) => {
      return { count: prevState.count + 1 }
    });
  }

  render() {
    return (<button
              onClick={() => this.updateCount()}
            >
              Clicked {this.state.count} times
            </button>);
  }
}

в основном, реквизит и состояние-это два способа, которыми компонент может знать, что и как визуализировать. Какая часть состояния приложения относится к состоянию, а какая к некоторому хранилищу верхнего уровня, больше связана с дизайном приложения, чем с тем, как работает React. Самый простой способ решить, ИМО, - это подумать, полезна ли эта конкретная часть данных для применения в целом, или это некоторая локальная информация. Кроме того, важно не дублировать состояние, поэтому, если какая-то часть данных может быть вычислена из реквизита - она должна быть рассчитана по реквизиту.

например, предположим, у вас есть некоторый раскрывающийся элемент управления (который обертывает стандартный HTML select для пользовательского стиля), который может a) выбрать некоторое значение из списка и b) быть открыт или закрыт (т. е. список опций отображается или скрыт). Теперь предположим, что ваше приложение отображает список элементов и фильтр раскрывающихся элементов управления для записей списка. Тогда было бы лучше передать активное значение фильтра в качестве опоры и сохранить открытое/закрытое состояние локальным. Кроме того, сделайте его функциональным, вы передадите обработчик onChange из родительского компонента, который будет вызван внутри раскрывающегося элемента и немедленно отправит обновленную информацию (новый выбранный фильтр) в магазин. С другой стороны, открытое/закрытое состояние можно сохранить внутри раскрывающегося компонента, потому что остальной части приложения все равно, открыт ли элемент управления, пока пользователь не изменит его значение.

следующий код не полностью работает, ему нужен CSS и раскрывающийся список обработки нажмите/размытие / изменение событий, но я хотел сохранить пример минимальным. Надеюсь, это поможет понять разницу.

const _store = {
    items: [
    { id: 1, label: 'One' },
    { id: 2, label: 'Two' },
    { id: 3, label: 'Three', new: true },
    { id: 4, label: 'Four', new: true },
    { id: 5, label: 'Five', important: true },
    { id: 6, label: 'Six' },
    { id: 7, label: 'Seven', important: true },
    ],
  activeFilter: 'important',
  possibleFilters: [
    { key: 'all', label: 'All' },
    { key: 'new', label: 'New' },
    { key: 'important', label: 'Important' }
  ]
}

function getFilteredItems(items, filter) {
    switch (filter) {
    case 'all':
        return items;

    case 'new':
        return items.filter(function(item) { return Boolean(item.new); });

    case 'important':
        return items.filter(function(item) { return Boolean(item.important); });

    default:
        return items;
  }
}

const App = React.createClass({
  render: function() {
    return (
            <div>
            My list:

            <ItemList   items={this.props.listItems} />
          <div>
            <Dropdown 
              onFilterChange={function(e) {
                _store.activeFilter = e.currentTarget.value;
                console.log(_store); // in real life, some action would be dispatched here
              }}
              filterOptions={this.props.filterOptions}
              value={this.props.activeFilter}
              />
          </div>
        </div>
      );
  }
});

const ItemList = React.createClass({
  render: function() {
    return (
      <div>
        {this.props.items.map(function(item) {
          return <div key={item.id}>{item.id}: {item.label}</div>;
        })}
      </div>
    );
  }
});

const Dropdown = React.createClass({
    getInitialState: function() {
    return {
        isOpen: false
    };
  },

  render: function() {
    return (
        <div>
            <select 
            className="hidden-select" 
          onChange={this.props.onFilterChange}
          value={this.props.value}>
            {this.props.filterOptions.map(function(option) {
            return <option value={option.key} key={option.key}>{option.label}</option>
          })}
        </select>

        <div className={'custom-select' + (this.state.isOpen ? ' open' : '')} onClick={this.onClick}>
            <div className="selected-value">{this.props.activeFilter}</div>
          {this.props.filterOptions.map(function(option) {
            return <div data-value={option.key} key={option.key}>{option.label}</div>
          })}
        </div>
      </div>
    );
  },

  onClick: function(e) {
    this.setState({
        isOpen: !this.state.isOpen
    });
  }
});

ReactDOM.render(
  <App 
    listItems={getFilteredItems(_store.items, _store.activeFilter)} 
    filterOptions={_store.possibleFilters}
    activeFilter={_store.activeFilter}
    />,
  document.getElementById('root')
);

состояние-это способ реагировать на информацию, хранящуюся в вашем компоненте.

предположим, у вас есть компонент, который должен получить некоторые данные с сервера. Обычно вы хотите сообщить пользователю, если запрос обрабатывается,если он не удался и т. д. Это часть информации, которая имеет отношение только к этому конкретному компоненту. Здесь государство вступает в игру.

обычно лучший способ определить состояние заключается в следующем:

class MyComponent extends React.Component {
  constructor() {
    super();
    this.state = { key1: value1, key2: value2 }    
  }
}

но в последних реализациях react native вы можете просто сделать:

class MyComponent extends React.Component {
  state = { key1: value1, key2: value2 }    
}

эти два примера выполняются точно так же, это просто улучшение синтаксиса.

Итак, что отличается от простого использования атрибутов объекта, как мы всегда имеем в программировании OO? Обычно информация, хранящаяся в вашем состоянии, не должна быть статичной, она будет меняться со временем, и Ваше представление необходимо будет обновить, чтобы отразить эти изменения. State предлагает эту функциональность в простой путь.

состояние должно быть INMUTABLE! и я не могу сделать достаточный акцент на этом. Что это значит? Это значит, что ты никогда не должен делать ничего подобного.

 state.key2 = newValue;

правильный способ сделать это:

this.setState({ key2: newValue });

С помощью этого.setState ваш компонент проходит через цикл обновления, и если какая-либо часть состояния изменяется, ваш метод рендеринга компонента будет вызван снова, чтобы отразить эти изменения.

Проверьте react docs для еще более расширенного объяснение: https://facebook.github.io/react/docs/state-and-lifecycle.html


государство - Это специальное изменяемое свойство, которое содержит данные компонента. он имеет значение по умолчанию при монтировании Componet.

реквизит - Это специальное свойство, которое является неизменяемым по своей природе и используется в случае передачи значения от родителя к ребенку. реквизит-это просто канал связи между компонентами, всегда перемещающийся сверху(Родительский) в buttom (дочерний).

ниже приводится полный пример combinding государства и реквизит :-

<!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>state&props example</title>

        <script src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
        <script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>
        <script src="https://unpkg.com/[email protected]/babel.min.js"></script>

      </head>
      <body>
      <div id="root"></div>
        <script type="text/babel">

            var TodoList = React.createClass({
                render(){
                    return <div className='tacos-list'>
                                {
                                    this.props.list.map( ( todo, index ) => {
                                    return <p key={ `taco-${ index }` }>{ todo }</p>;
                            })}
                            </div>;
                }
            });

            var Todo = React.createClass({
                getInitialState(){
                    return {
                        list : [ 'Banana', 'Apple', 'Beans' ]       
                    }
                },
                handleReverse(){
                    this.setState({list : this.state.list.reverse()});
                },
                render(){
                    return <div className='parent-component'>
                              <h3 onClick={this.handleReverse}>List of todo:</h3>
                              <TodoList list={ this.state.list }  />
                           </div>;
                }
            });

            ReactDOM.render(
                <Todo/>,
                document.getElementById('root')
            );

        </script>
      </body>
      </html>

реквизит просто сокращенно для свойств. Реквизит-это то, как компоненты разговаривают друг с другом. Если вы вообще знакомы с React, вы должны знать, что реквизит течет вниз от родительского компонента.

существует также случай, когда вы можете иметь реквизит по умолчанию, чтобы реквизит был установлен, даже если родительский компонент не передает реквизит.

вот почему люди ссылаются на реакцию как имеющую однонаправленный поток данных. Тебе нужно немного собраться с мыслями, и я ... вероятно, блог об этом позже, но пока просто помните: потоки данных от родителя к ребенку. Реквизит неизменен (причудливое слово для него не меняется)

Итак, мы счастливы. Компоненты получают данные от родителя. Все улажено, да?


короче.

значения реквизита не могут быть изменены [неизменяемые]

значения состояния могут быть изменены с помощью метода setState [mutable]


в ответ на первоначальный вопрос о неизменяемости реквизита, они говорят, что они неизменяемы что касается дочернего компонента но изменчивы в родителе.


компоненты React используют состояние для чтения / записи внутренних переменных, которые могут быть изменены/мутированы, например:

this.setState({name: 'Lila'})

React props-это специальный объект, который позволяет программисту получать переменные и методы из родительского компонента в дочерний компонент.

Это что-то вроде окон и дверей дома. Реквизит также неизменяемый дочерний компонент не может изменять / обновлять их.

есть несколько методов, которые помогают слушать, когда реквизит изменено родительским компонентом.


Это моя текущая точка зрения относительно объяснения между состоянием и реквизитом

  1. состояние похоже на вашу локальную переменную внутри вашего компонента. Вы можете манипулировать значение state с помощью set state. Затем вы можете передать значение государства например, для вашего дочернего компонента.

  2. реквизит-это значение, которое точно находится внутри вашего магазина redux, это на самом деле происходит из состояния, которое возникло из редуктора. Ваши компоненты должен быть подключены вместе, чтобы получить значение из реквизита. Вы также можете пройти ваш реквизит значение для вашего дочернего компонента


В общем случае состояние одного компонента (родительского) является prop для дочернего компонента.

  1. состояние находится в компоненте, где в качестве реквизита передаются от родителя к ребенок.
  2. реквизит, как правило, неизменны.

    class Parent extends React.Component {
        constructor() {
            super();
            this.state = {
                name : "John",
            }
        }
        render() {
            return (
                <Child name={this.state.name}>
            )
        }
    }
    
    class Child extends React.Component {
        constructor() {
            super();
        }
    
        render() {
            return(
                {this.props.name} 
            )
        }
    }
    

в приведенном выше коде у нас есть родительский класс (Parent), который имеет имя в качестве своего состояния, которое передается дочернему компоненту (дочернему классу) в качестве prop, и дочерний компонент отображает его с помощью {это.реквизит.имя}


состояние:

  1. состояния изменчивы.
  2. государства, связанные с отдельными компонентами не могут использоваться другими компонентами.
  3. состояния инициализируются при монтировании компонентов.
  4. состояния используются для визуализации динамических изменений в компоненте.

реквизиты:

  1. реквизиты неизменяемы.
  2. вы можете передавать реквизит между компонентами.
  3. реквизит в основном используется для связи между компонентами.Вы можете напрямую переходить от родителя к ребенку. Для перехода от ребенка к родителю вам нужно использовать концепцию подъема состояний.

class Parent extends React.Component{
  render()
  {
     return(
        <div>
            <Child name = {"ron"}/>
        </div>
      );
  }
}

class Child extends React.Component{
{
    render(){
      return(
         <div>
              {this.props.name}
        </div>
      );
     }
}

У вас есть некоторые данные, которые вводятся пользователями где-то в приложении.

  1. компонент, в который вводятся данные, должен иметь эти данные в своем государство потому что он должен манипулировать и менять его во время ввода данных

  2. в любом другом месте приложения данные должны передаваться как реквизит для всех остальных компонентов

да реквизит но они изменяются в "источнике", а затем просто стекают оттуда. Так что реквизит неизменен в контексте компонента, получая их.

например. экран ссылочных данных, где пользователи редактируют список поставщиков, будет управлять этим в состоянии, которое затем будет иметь действие, вызывающее сохранение обновленных данных в ReferenceDataState, которое может быть на один уровень ниже AppState, а затем этот список поставщиков будет передан в качестве реквизита всем компонентам, которые нужно было его использовать.


реквизит-это значения, объекты или массивы, переданные в компонент при рендеринге. Эти реквизиты часто являются значениями, необходимыми в компоненте для создания пользовательского интерфейса, установки определенных функций по умолчанию или заполнения полей. Реквизит также может быть передан в виде функций, передаваемых из родительского компонента, которые могут быть вызваны дочерним компонентом.

состояние управляется в компоненте (дочернем или родительском).

вот определение, которое я нашел для поддержки это:

enter image description here