2017-08-10 18 views
1

這裏是我當前的代碼: (2個文件&類: 「FoodStandComponent.jsx」)重構代碼不具有的setState的Html

/* ************************************* */ 
/* ********  IMPORTS  ******** */ 
/* ************************************* */ 
import uuid from 'uuid/v4'; 
import { Card, CardBlock, Button, InputGroup, Input } from 'reactstrap'; 
import React, { Component } from 'react'; 
import ProviderInfos from '../ProviderInfos/ProviderInfos'; 
import InputType from './InputType/InputType'; 

/* ************************************* */ 
/* ********  VARIABLES  ******** */ 
/* ************************************* */ 

const propTypes = { 
    newInput: React.PropTypes.array, 
    exportInput: React.PropTypes.func, 
}; 

/* ************************************* */ 
/* ********  COMPONENT  ******** */ 
/* ************************************* */ 
class FoodStandComponent extends Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      newInput: [ 
       { name: 'Pretzel', id: uuid() }, 
       { name: 'Curry', id: uuid() }, 
       { name: 'Wurst', id: uuid() }, 
      ], 
      InValue: '', 
     }; 
     this.add = this.add.bind(this); 
     this.remove = this.remove.bind(this); 
    } 

    add = (name) => { 
     const ninput = this.state.newInput.concat({ name, id: uuid(), value: this.state.InValue }); 
     this.setState({ 
      newInput: ninput, 
      InValue: '', 
     }); 
    }; 

    remove = (id, name) => { 
     const toBeRemoved = this.state.newInput.filter(x => x.name === name).pop(); 
     if (toBeRemoved) { 
      this.setState({ 
       newInput: this.state.newInput.filter(x => x.name !== name).concat(
        this.state.newInput.filter(x => x.name === name && x.id !== toBeRemoved.id), 
       ), 
      }); 
     } 
    }; 

    render() { 
     console.log(); 
     const cubeFifteenOrUnder = this.state.newInput.filter(x => x.name === 'Pretzel') 
      && this.state.newInput.filter(x => x.name === 'Pretzel').length <= 13; 
     const dsoFifteenOrUnder = this.state.newInput.filter(x => x.name === 'Curry') 
      && this.state.newInput.filter(x => x.name === 'Curry').length <= 13; 
     const multiFifteenOrUnder = this.state.newInput.filter(name => name === 'Wurst') 
      && this.state.newInput.filter(x => x.name === 'Wurst').length <= 13; 

     return (
      <Card> 
       <CardBlock className="main-table"> 
        <fieldset> 
         <legend>Pretzels</legend> 
         <InputGroup> 
          <Input placeholder="Pretzel" /> 
          <ProviderInfos type="Pretzel" /> 
          { cubeFifteenOrUnder && (
           <div className="plus" onClick={() => this.add('Pretzel')}> 
            <i className="fa fa-plus" aria-hidden="true" /> 
           </div> 
          ) } 
          { !cubeFifteenOrUnder && (
           <div className="plus-off"> 
            <i className="fa fa-plus" aria-hidden="true" /> 
           </div> 
          ) } 
         </InputGroup> 
         {this.state.newInput.map((mapStorageVariable) => { 
          if (mapStorageVariable.name === 'Pretzel') { 
           return (<InputType 
            id={mapStorageVariable.id} 
            placeholder={mapStorageVariable.name} 
            value={mapStorageVariable.value} 
            onRemove={() => this.remove(mapStorageVariable.id, mapStorageVariable.name)} 
           />); 
          } 
          return null; 
         })} 
        </fieldset> 
        <fieldset> 
         <legend>Curries</legend> 

         <InputGroup> 
          <Input placeholder="Curry" /> 
          <ProviderInfos type="Curry" /> 
          { dsoFifteenOrUnder && (
           <div className="plus" onClick={() => this.add('Curry')}> 
            <i className="fa fa-plus" aria-hidden="true" /> 
           </div> 
          ) } 
          { !dsoFifteenOrUnder && (
           <div className="plus-off"> 
            <i className="fa fa-plus" aria-hidden="true" /> 
           </div> 
          ) } 
         </InputGroup> 
         {this.state.newInput.map((mapStorageVariable) => { 
          if (mapStorageVariable.name === 'Curry') { 
           return (<InputType 
            id={mapStorageVariable.id} 
            placeholder={mapStorageVariable.name} 
            value={mapStorageVariable.value} 
            onRemove={() => this.remove(mapStorageVariable.id, mapStorageVariable.name)} 
           />); 
          } 
          return null; 
         })} 
        </fieldset> 
        <fieldset> 
         <legend>Wursts</legend> 
         <InputGroup> 
          <Input placeholder="Wurst" /> 
          <ProviderInfos type="Wurst" /> 
          { multiFifteenOrUnder && (
           <div className="plus" onClick={() => this.add('Wurst')}> 
            <i className="fa fa-plus" aria-hidden="true" /> 
           </div> 
          ) } 
          { !multiFifteenOrUnder && (
           <div className="plus-off"> 
            <i className="fa fa-plus" aria-hidden="true" /> 
           </div> 
          ) } 
         </InputGroup> 
         {this.state.newInput.map((mapStorageVariable) => { 
          if (mapStorageVariable.name === 'Wurst') { 
           return (<InputType 
            id={mapStorageVariable.id} 
            placeholder={mapStorageVariable.name} 
            value={mapStorageVariable.value} 
            onRemove={() => this.remove(mapStorageVariable.id, mapStorageVariable.name)} 
           />); 
          } 
          return null; 
         })} 
        </fieldset> 
        <Button color="secondary">Options</Button>{' '} 
        <Button id="btn">Exécuter</Button> 
       </CardBlock> 
      </Card> 
     ); 
    } 
} 
SearchExtendedComponent.propTypes = propTypes; 

export default SearchExtendedComponent; 

(和InputTypeComponent.jsx)

/* ************************************* */ 
/* ********  IMPORTS  ******** */ 
/* ************************************* */ 
import ProviderInfos from '../../ProviderInfos/ProviderInfos'; 
import React, { Component } from 'react'; 
import { Card, CardBlock, Button, InputGroup, Input } from 'reactstrap'; 
/* ************************************* */ 
/* ********  VARIABLES  ******** */ 
/* ************************************* */ 

/* ************************************* */ 
/* ********  COMPONENT  ******** */ 
/* ************************************* */ 

export default class InputTypeComponent extends Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      type: '', 
     }; 
    } 

    onRemove =() => { 
     this.props.onRemove(this.props.id); 
    } 

    onChange =() => { 
     this.props.onChange(this.props.id); 
    } 

    render() { 
     const { placeholder, id, value } = this.props; 
     const { type } = this.state; 
     this.type = placeholder; 
     return (
      <InputGroup key={id}> 
       <Input placeholder={placeholder} />{value} 
       <ProviderInfos type={this.type} /> 
       <div className="minus" onClick={this.onRemove}> 
        <i className="fa fa-minus" aria-hidden="true" /> 
       </div> 
      </InputGroup> 
     ); 
    } 
} 

我m試圖通過將「添加」和「刪除」按鈕重構爲一個函數來獲取列表。

正如你可以看到以上感謝@Jacky Choo的回答&代碼我幾乎在那裏,但問題是,我已經失去了我以前的功能,我想刪除刪除線,當我點擊它自己刪除按鈕。 this is what my app looks like

當我點擊這個減號時,包含文本和改變的複選框的行保留。 和最後一行消失。

更新:

修好了! 通過改變刪除這個我得到我的預期結果。是的,刪除的下面的行會被重置,但是Redux可以處理這些行。對@Jacky Choo大肆宣揚,他基本上爲我着想!

remove = (id, name) => { 
     this.setState({ 
      newInput: this.state.newInput.filter(x => x.name === name && x.id !== id), 
     }); 
    }; 
+0

我覺得你這樣做是錯的,如果你把HTML到您的狀態開始。理想狀態應該是那個。該HTML基於從該州收到的數據呈現, – dcodesmith

+0

我知道這就是爲什麼我試圖解決它....幫助我! – tatsu

+0

那麼你可以返回不同的函數,返回HTML基於一個handlerVariable – Nocebo

回答

1

測試在我身邊的工作(替換了一些定製類正常輸入框未提供)

加入JSX進入狀態看起來不正確,我已經修改了將食物作爲數組存儲在狀態中的代碼,每個代碼都映射到呈現輸入字段的組件。

希望它可以幫助

import React, { Component } from 'react'; 

const FoodInput = ({ foodName, id }) => { 
    return (
     <input placeholder={foodName} key={id} /> 
    ); 
} 

export default class PretzelStandComponent extends Component { 
    constructor(props) { 
     super(props); 
     const uuid = require('uuid/v1'); 
     this.state = { 
      Foods: [ 
       {name: "Pretzel", id: uuid()}, 
       {name: "Curry", id: uuid()}, 
       {name: "Wurst", id: uuid()} 
      ] 
     } 
    } 

    componentDidMount() { 
    } 

    addFood(name) { 
     const uuid = require('uuid/v1'); 
     this.setState({ 
      Foods: this.state.Foods.concat({ name, id: uuid() }) 
     }); 
    } 

    removeFood(name) { 
     var foodToBeRemoved = this.state.Foods.filter(x => x.name === name).pop() 
     if (foodToBeRemoved){ 
      this.setState({ 
      Foods: this.state.Foods.filter(x => x.name !== name).concat(
       this.state.Foods.filter(x => x.name === name && x.id !== foodToBeRemoved.id) 
      ) 
     }); 
     }  
    } 

    render() { 
     return (
      <div> 
        <fieldset> 
         <legend>Pretzels</legend> 
         {this.state.Foods.map(food => { 
          if (food.name === "Pretzel") { 
           return (<FoodInput foodName={food.name} key={food.id} {...food} />) 
          } 
          else 
          { 
           return null 
          } 
         })} 
         <button onClick={() => this.addFood("Pretzel")}>Add a Pretzel</button> 
         <button onClick={() => this.removeFood("Pretzel")}>Remove a Pretzel</button> 
        </fieldset> 
        <fieldset> 
         <legend>Curry</legend> 
         {this.state.Foods.map(food => { 
          if (food.name === "Curry") { 
           return (<FoodInput foodName={food.name} key={food.id} {...food} />) 
          } 
          else 
          { 
           return null 
          } 
         })} 
         <button onClick={() => this.addFood("Curry")}>Add a Curry</button> 
         <button onClick={() => this.removeFood("Curry")}>Remove a Curry</button> 
        </fieldset> 
        <fieldset> 
         <legend>Wurst</legend> 
         {this.state.Foods.map(food => { 
          if (food.name === "Wurst") { 
           return (<FoodInput foodName={food.name} key={food.id} {...food} />) 
          } 
          else 
          { 
           return null 
          } 
         })} 
         <button onClick={() => this.addFood("Wurst")}>Add a Wurst</button> 
         <button onClick={() => this.removeFood("Wurst")}>Remove a Wurst</button> 
        </fieldset> 
       </div> 
     ); 
    } 
} 
+0

耶完美!非常感謝!這個解決方案爲我工作!對不起,我同時在https://stackoverflow.com/questions/45585895/delete-remove-specific-collection-item上添加了一個規範,因此編輯了我的代碼,但無論如何我都能夠實現您的答案(最後^^ ') – tatsu

+0

@tatsu,很高興它爲你工作,但我很好奇;這個解決方案與我的有何不同? – Chris

+0

我編輯的OP中的一個?它從點擊刪除按鈕中刪除行,而不是總是刪除最下面的那一行。但它確實很奇怪,除了對inderOutOfBounds和其他內容更加謹慎以外,你的刪除函數看起來像是一樣的。 – tatsu

1

你可以做水木清華這樣的:

export default class PretzelStandComponent extends Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      handler: 1 
      }; 
     ... 
    } 

    handleHTML =() => { 
     switch(this.state.handler){ 
     case 1: 
      return this.returnHTML(); 
     } 
    } 

    //Set handlerVariable in your functions instead of setting html 

    //Return html 
    returnHTML =() => { 
     return (<div/>); 
    } 

    render(){ 
     return(<div>{this.handleHTML()}</div>); 
    } 
+0

你明白了嗎? – Nocebo

+0

完全沒有:/ – tatsu

1

的可以說是最好的,最簡單的解決方案是負責存儲每個成分的數組,然後通過每個陣列中的映射渲染。

更重要的是,你可以只使用一個功能爲遞增或遞減您的陣列,因爲他們做的只是創建一個新的uuid,但他們返回相同的JSX更多或更少。

由於這種相似性,您可以使用這兩個功能,唯一的參數就是要添加/刪除的成分的名稱。


這是一個工作演示。我已將<Input /><ProviderInfos />中的一些組件替換爲僅用於演示的<span>

我還用假鑰匙取代了你的uuid()以使其正常工作。

class PretzelStandComponent extends React.Component { 
 

 
    constructor(props) { 
 
     super(props); 
 
     this.state = { 
 
      inputPretzel: [], 
 
      inputCurry: [], 
 
      inputWurst: [] 
 
      }; 
 
     this.increment = this.increment.bind(this); 
 
     this.decrement = this.decrement.bind(this); 
 
    } 
 
    
 
    increment = (name) => { 
 
     //const uuid = require('uuid/v1'); 
 
     //uuid(); 
 
     let uuid = this.state['input' + name].length+1; 
 

 
     let n = this.state['input' + name].slice(); 
 
     n.push(uuid); 
 
     this.setState({['input' + name]: n});   
 
    } 
 

 
    decrement = (name) => { 
 
     let n = this.state['input' + name]; 
 
     n.pop(); 
 
     this.setState({['input' + name]: n}); 
 
    } 
 

 
    render() { 
 
     return (
 
      <div> 
 
       <div className="main-table"> 
 
        <fieldset> 
 
         <legend>Pretzels</legend> 
 
         {this.state.inputPretzel.map(
 
          key => { 
 
          return <span>{key}</span>; 
 
          }) 
 
         } 
 
         <button onClick={this.increment.bind(this, "Pretzel")}>Add a Pretzel</button> 
 
         <button onClick={this.decrement.bind(this, "Pretzel")}>Remove a Pretzel</button> 
 
        </fieldset> 
 
        <fieldset> 
 
         <legend>Curry</legend> 
 
         {this.state.inputCurry.map(
 
          key => { 
 
          return <span>{key}</span>; 
 
          }) 
 
         } 
 
         <button onClick={this.increment.bind(this, "Curry")}>Add Curry</button> 
 
         <button onClick={this.decrement.bind(this, "Curry")}>Remove Curry</button> 
 
        </fieldset> 
 
        <fieldset> 
 
         <legend>Wurst</legend> 
 
         {this.state.inputWurst.map(
 
          key => { 
 
          return <span>{key}</span>; 
 
          }) 
 
         } 
 
         <button onClick={this.increment.bind(this, "Wurst")}>Add Wurst</button> 
 
         <button onClick={this.decrement.bind(this, "Wurst")}>Remove Wurst</button> 
 
        </fieldset> 
 
        <button color="secondary">Options</button>{' '} 
 
        <button id="btn">Exécuter</button> 
 
       </div> 
 
      </div> 
 
     ); 
 
    } 
 
} 
 

 
ReactDOM.render(<PretzelStandComponent />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="app"></div>

+0

nah每行都有自己的刪除按鈕,它應該刪除正確的行,這個解決方案沒有考慮到這一點。謝謝。 – tatsu

+0

@tatsu,你的代碼似乎沒有,我的解決方案是基於你的代碼。你的問題是*「我試圖獲得所有」增量「函數調用的單個函數,這將負責處理進入集合」*的HTML,我想我已經在這裏提供了 - 有一個單一的函數函數分別添加和刪除元素。 – Chris

+0

是的我知道我應該更新問題以反映我目前的代碼?雖然這個問題在技術上是正確的,但是我無法想象在現實生活中使用這樣一些代碼。 – tatsu