2017-02-10 3 views
1

Я пытаюсь отобразить компонент Need, когда мы нажимаем на ссылку «Добавить». ниже мой код для основного компонента:рендеринг реагирует на компоненты при нажатии

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { Hand } from './hand.js'; 
import { Need } from './need.js'; 

class App extends React.Component{ 
    constructor() { 
    super(); 
    this.processHand = this.processHand.bind(this); 
    this.addNeed = this.addNeed.bind(this); 
    this.state = { 
     inhandMoney : " ", 
     renderNeed: false, 
    } 

    } 

    processHand(e){ 
    e.preventDefault(); 
    const handMoneyReceived = this.handMoney.value; 
    this.setState({ 
     inhandMoney: handMoneyReceived 
    });  
    } 

    addNeed(e){ 
    e.preventDefault(); 
    this.setState({ 
     renderNeed:true 
    }); 
    } 

    render(){ 

    const passNeed = ( 
      <Need/> 
    ); 

    return(
     <div> 
      <div className ="hand"> 
      <form onSubmit = {this.processHand}> 
       <input type="text" ref= {ref => this.handMoney = ref}/> 
       <input type="submit"/> 
      </form> 
      <Hand handMoney = {this.state.inhandMoney}/> 
      <Need/> 
      </div> 
      {this.state.renderNeed ? passNeed : null} 
      <a href="#" className="add" onClick = {this.addNeed}>add</a> 
     </div> 
    ) 
    } 
} 

ReactDOM.render(<App />, document.getElementById('container')); 

и ниже моя потребность компонент только в случае, если:

import React from 'react'; 

export class Need extends React.Component{ 
constructor() { 
    super(); 
    this.processNeed = this.processNeed.bind(this); 
    this.state ={ 
     why: " ", 
     howMuch: 0 
    } 

} 

processNeed(e){ 
    e.preventDefault(); 
    const why=this.why.value; 
    const howMuch=this.howMuch.value; 
    this.setState({ 
     why:why, 
     howMuch:howMuch 
    }); 
} 

    render(){ 
     return(
      <div className ="need"> 
      <form onSubmit = {this.processNeed}> 
       <input type="text" ref= {ref => this.why = ref}/> 
       <input type="text" ref= {ref => this.howMuch = ref}/> 
       <input type="submit"/> 
      </form> 
      <div> 
       <h1>{this.state.why}</h1> 
       <h1>{this.state.howMuch}</h1> 
      </div> 
      </div>    
     ) 
    } 
} 

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

+0

методы класса должны быть "связаны". @john_omalley имеет ответ ниже. См. Http://stackoverflow.com/a/30721098/368697 для привязки методов класса, которые вы собираетесь использовать в качестве обратных вызовов. –

+0

Вы получили решение или все еще сталкиваетесь с проблемой? –

ответ

1

Из вашего объяснения, я получаю, что вы хотите добавить компонент Need при каждом нажатии на ссылку add.

Код, который вы указали, не работает так, как вы хотите, чтобы он работал из-за неправильного понимания метода render(). Каждый раз, когда вы нажимаете на ссылку add, ваш компонент <Need /> будет перерисовываться, но есть только один компонент <Need />, который повторно отображается каждый раз. Если вы хотите визуализировать новый компонент каждый раз, когда нажимается ссылка на ссылку add. Вам нужно будет использовать массив, который будет содержать все компоненты <Need />.

Чтобы достичь этого, я создал переменную состояния с именем needArray. Каждый раз, когда вы нажимаете ссылку add, в этой переменной состояния будет добавлен новый компонент <Need />, который будет отображаться.

constructor(props) { 
    super(props) 
    this.state = {renderNeed: false, needArray: []} 
    this.addNeed = this.addNeed.bind(this) 
} 

addNeed(e) { 
    e.preventDefault(); 
    // any another better approach can be used to generate unique key. I've used Math.random() for demo only. 
    this.setState({ 
     renderNeed: true, 
     needArray: [<Need key={Math.random()}/>, ...this.state.needArray] 
    }) 
} 

render() { 
    return (
     <div> 
     <a href="#" onClick = {this.addNeed}>add</a> 
     {this.state.renderNeed ? this.state.needArray : null} 
     </div> 
    ) 
} 

Вот ссылка на рабочую скрипку. Для краткости я добавил только необходимый код. JSFiddle

0
{this.state.renderNeed ? passNeed : null} 

заменить

{this.state.renderNeed && <Need/> } 
+0

не работает! та же проблема. – ashish

1

Try: <a href="#" className="add" onClick = {this.addNeed.bind(this)}>add</a>

+0

все еще не работает! – ashish

+0

Право - пропустил это. Вам нужно будет моделировать массив элементов в состоянии - вместо того, чтобы начинать с булевского флага с ложным запуском с [], а затем каждый новый клик объединяет новый элемент. вам необходимо отобразить один элемент для каждого элемента массива. см. реакцию документов на рендеринг массивов элементов (например, свойство «ключ». –

0

1) Один из способов достижения этой цели является:

addNeed(e){ 
    e.preventDefault(); 
    this.setState({ 
     needKey: Math.random() 
    }); 
} 

И в рендеринге вы можете добавить этот ключ:

<Need key={this.state.needKey} /> 

2) Другой способ:

addNeed(e){ 
    e.preventDefault(); 
    this.setState(this.state); 
} 

3) Кроме того, может быть сделано с forceUpdate. Однако, как правило, не рекомендуется:

addNeed(e) { 
    e.preventDefault(); 
    this.forceUpdate() 
} 
+0

не работает !!!! – ashish

0

Я хотел бы создать начальное состояние ключа с пустым массивом, каждый раз, когда вы нажмите кнопку «Добавить», вы бы увеличивать размер массива, а затем вы бы отобразить массив на render(). Что-то вроде этого:

constructor() { 
super(); 
    this.processHand = this.processHand.bind(this); 
    this.addNeed = this.addNeed.bind(this); 
    this.state = { 
    inhandMoney : " ", 
    fields: [], 
    } 
} 

addNeed(e){ 
    e.preventDefault(); 
    this.setState({ 
    fileds: this.state.fields.push(1), 
    }); 
} 

render() { 
    <div> 
    <div className="hand"> 
     <form onSubmit={this.processHand}> 
     <input type="text" ref={ref => this.handMoney = ref}/> 
     <input type="submit"/> 
     </form> 
     <Need/> 
    </div> 
    {this.state.fields.map(i => <Need key={i} />)} 
    <a href="#" className="add" onClick={this.addNeed}>add</a> 
    </div> 
} 
1

Если вы хотите сохранить рендеринг коллекции потребностей, вы можете хранить массив в вашем штате, который может отслеживать ваши потребности.

В противном случае, на основании этой цитаты -

на первый компонент нужно визуализируется без condition.and, когда я нажимаю на «добавить» компонент Need визуализируется еще раз, но когда я нажимаю «добавить» ссылку во второй раз, я не вижу никаких изменений.

Кажется, что вы хотите сделать на основе изменений отслеживаемых ваши renderNeed булева

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

это хороший ресурс: ReactJS - Does render get called any time "setState" is called?

Как надуманный Например, если вы действительно хотите, чтобы «повторно вызывать» компонента, вы могли бы сделать что-то тривиальное, как создание тумблер для renderNeed

addNeed(e){ 
    e.preventDefault(); 
    this.setState((prevState, props) => ({ 
     renderNeed: !prevState.renderNeed 
    }); 
    } 

это не рекомендуется делать это, потому что ваша функция addNeed не делает то, что это название говорит .. .

также немного скрипки, чтобы продемонстрировать, что она вновь делает

https://jsfiddle.net/jwm6k66c/2131/

Надеется, что это помогает.

2

Ниже приведено решение для решения проблемы . Я старался быть как можно ближе к вашему коду.

https://jsfiddle.net/birjubaba/t0yusos9/3/

Объяснение дается @sean пятно на.

По умолчанию вызов setState будет выполнять компонент rerender, независимо от того, какие действительные аргументы передаются в setState. Так что да, это должно быть рендеринга. Это, кажется, не перерисовка, потому что, ну, это всегда отображая то же самое после первого щелчка, потому что renderNeed всегда верно после каждого щелчка

Реагировать поддерживать виртуальный DOM и все DOM манипуляции выполняются в этом виртуальном DOM (перед обновлением фактического DOM). Добавление компонента Need является манипуляцией DOM. Итак, первый раз, когда мы нажимаем «добавить», он фактически обновляет виртуальную DOM, чтобы добавить новый Need. Теперь отреагирует алгоритм diff, и он обновляет фактический DOM. Итак, компонент Need отображается в пользовательском интерфейсе.DOM будет выглядеть, как показано ниже:

div 
|- div (class=hand) 
     |-form 
     |-input (type=text) 
     |-input (type=submit) 
     |- Hand 
     |- Need 
|-Need (added by clicking on add anchor tag) 
|-a (class=add) 

В следующий раз, когда «добавить» щелчок, this.state.renderNeed верно снова, так, React будет пытаться добавлять нужна компоненты в виртуальном DOM (из-под кодом) ,

{this.state.renderNeed ? passNeed : null} 
<a href="#" className="add" onClick = {this.addNeed}>add</a> 

Но перед добавлением Need, React дифф алгоритм будет работать, и он будет видеть, что есть уже потребность компонент присутствует в виртуальном (и фактической) DOM, который в точности похож на тот, что пытался добавить. React будет думать, что DOM одинаковы, и ничто не обновляется в пользовательском интерфейсе.

Вашего требования оного является то, что, как показано ниже:

div 
|- div (class=hand) 
     |-form 
     |-input (type=text) 
     |-input (type=submit) 
     |- Hand 
     |- Need 
|-Need (added by clicking on add anchor tag) 
|-Need (added by clicking on add anchor tag) 
|-Need (added by clicking on add anchor tag) 
|-Need (added by clicking on add anchor tag) 
|-a (class=add) 

Это может быть достигнуто путем поддержания массива Need компонента и делают их щелкать добавить. Алгоритм React diff позаботится обо всех оптимизации для обновления виртуальной DOM и фактического DOM.

Я бы посоветовал вам пройти через два замечательных места, где объясняется алгоритм реагирования diff.

  1. Поиск "Примирение - React" в Google и открыть фейсбук реагировать страницу из результатов поиска
  2. https://calendar.perfplanet.com/2013/diff/
+1

ha! спасибо за подтверждение моего ответа :) –

+0

Основное правило оператора '&&', если первое верно, а затем второе условие оценивается. Итак, здесь, если 'this.state.renderNeed' истинно, тогда выполняется второе условие, которое является вызовом метода (this.renderNeedArray()'. Он просто гарантирует, что когда 'this.state.renderNeed' является истинным, тогда только' renderNeedArray () '. –

+0

спасибо, также я хотел бы добавить все значения« насколько много »во всем необходимом компоненте после того, как я завершил добавление необходимости. Есть ли способ сделать это? – ashish

Смежные вопросы