2017-01-25 4 views
0

このコードを実行すると、ローカルストレージ内の各レシピ項目ごとにブートストラップパネルグループが取得されます。レシピを削除しようとすると、時には正しいレシピが削除されることがあります。コンソールには、正しいレシピがローカルストレージから削除されたことが表示されますが、アプリコンポーネントが状態をリセットする何らかの理由で間違ったレシピが削除されます。私はボトムアップからレシピを削除しようとすると動作することに気付きました。しかし、最初のレシピをクリックすると、下のレシピが削除されます。React:ローカルストレージに基づく状態を設定する

私はこれが簡単な修正だと知っていますが、私は新しい視点が必要です。みんな、ありがとう! はまた、コード内のインデントの申し訳ありませんがない - スタックオーバーフローが間隔

class App extends Component { 
    constructor() { 
    super(); 
    this.deleteRecipe = this.deleteRecipe.bind(this) 
    this.state = { 
    recipeData: JSON.parse(localStorage.getItem('recipeData')) 
} 
} 

deleteRecipe() { 
this.setState({recipeData: JSON.parse(localStorage.getItem('recipeData'))}) 
} 

render() { 
return (
    <div className="App"> 
    <div className="App-header"> 
     <img src={logo} className="App-logo" alt="logo" /> 
     <h2>Welcome to React Recipe Box!</h2> 
    </div> 

    <div className="container"> 
     {this.state.recipeData.map(recipe => { 
     return (
     <Recipe name={recipe.name} ingredients={recipe.ingredients} deleteRecipe={this.deleteRecipe}/> 
     ) 
     })} 
    </div> 
    </div> 
); 
} 
} 

class Recipe extends Component { 
constructor() { 
super(); 
    this.onDeleteRecipe = this.onDeleteRecipe.bind(this) 
} 

componentWillMount(){ //set state when component is about to mount 
this.state = { 
    name: this.props.name, 
    ingredients: this.props.ingredients, 

} 
} 

onDeleteRecipe() { 
var recipeList = JSON.parse(localStorage.getItem('recipeData')); 
for(var i = 0; i < recipeList.length; i++) { 
    if(recipeList[i].name === this.state.name) { 
    recipeList.splice(i, 1); 
    console.log("Deleted " + this.state.name, recipeList); 
    localStorage.removeItem('recipeData'); 
    localStorage.setItem('recipeData', JSON.stringify(recipeList)); 

    this.props.deleteRecipe(); 
    } 
} 

} 

render() { 
return (
<div> 
    <div className="panel-group"> 
    <div className="panel panel-primary"> 
     <div className="panel-heading"> 
     <h2 className="panel-title"> 
      <a data-toggle="collapse" data-target={'#' + (this.state.name).replace(/\s/g, '')} href={'#' + (this.state.name).replace(/\s/g, '')}> 
      {this.state.name} 
      </a> 
     </h2>>    
     </div> 
    <div id={(this.state.name).replace(/\s/g,'')} className="panel-collapse collapse"> 
     <div className="panel-body"> 
      {this.state.ingredients.map(ingredient => { 
      return <li className="list-group-item">{ingredient}</li> 
      })} 
      <div className="btn-group"> 
      <button className="btn btn-sm btn-info" data-toggle="modal" 
        data-target={'#' + (this.state.name).replace(/\s/g, '') + 'EditModal'}>Edit</button> 
      <button className="btn btn-sm btn-danger" data-toggle="modal" 
        data-target={'#' + (this.state.name).replace(/\s/g, '') + 'RemoveModal'} 
        >Delete</button> 
      </div> 
     </div> 
    </div> 
    </div> 
    </div> 


    <div className="modal modal-lg" id={(this.state.name).replace(/\s/g, '') + 'EditModal'} > 
     <div className="modal-content"> 
      <div className="modal-header"> 
      <h2>Edit {this.state.name}</h2> 
      </div> 
      <div className="modal-body"> 
      <ul className="list-group list-unstyle"> 
       {this.state.ingredients.map(ingredient => { 
       return <li className="list-group-item">{ingredient}</li> 
       })} 
      </ul> 
      </div> 
      <div className="modal-footer"> 
      <div className="btn-group"> 
       <button className="btn btn-sm btn-info" data-dismiss="modal">Save</button> 
       <button className="btn btn-sm btn-danger" data-dismiss="modal">Close</button> 
      </div> 
      </div> 
     </div> 
     </div> 


     <div className="modal modal-lg" id={this.state.name.replace(/\s/g, '') + 'RemoveModal'}> 
     <div className="modal-content"> 
      <div className="modal-body"> 
      <h3>This will remove the selected recipe. Are you sure?</h3> 
      </div> 
      <div className="modal-footer"> 
      <div className="btn-group"> 
       <button className="btn btn-sm btn-danger" data-dismiss="modal" onClick={this.onDeleteRecipe}>Delete</button> 
       <button className="btn btn-sm btn-info" data-dismiss="modal">Close</button> 
      </div> 
      </div> 
     </div> 
     </div> 
</div> 
); 
} 
} 

export default App; 

答えて

1

とあまりにもフレンドリーされていなかった私はまだ初心者だけど、...私はいくつかのFreeCodeCampのための反応レシピボックスを構築しました何ヶ月も前に、私はあなたのものと私の削除機能を比較するためにそれを引っ張った。

localstorageを私の場合とは違って扱うことに気付きました。 (私のやり方が最善のことでもなくても!)何とか問題がそのデザインに根ざしているのだろうかと思います。あなたのdelete関数はlocalStorageに行き、変更を加えます。次に、setStateを実行して、レシピデータを「再取得」するように並べ替えます。

これとは対照的に、私のアプリはlocalStorageから変数を宣言し、その変数と同じになるようにthis.state.recipeArrayを設定しました。その後、私の編集/追加/削除機能はすべてthis.state.recipeArray, localStorageに変更されます。みかんのように:バックのlocalStorageにthis.state.recipeArrayへの変更を取得するために

handleDelete: function(e) { 
    e.preventDefault(); 

    var replacementRecipeArray = this.state.recipeArray.filter((recipe) => recipe.title !== e.target.name); 
    //dot-filter with ES6 fat-arrow returns all items where title doesn't match the one we clicked; IOW, it removes the one we want to delete 

    this.setState({ 
     recipeArray: replacementRecipeArray 
    }); 

    } 

、私はlocalStorage.setItem私はページをレンダリングするすべての時間を行います。

render() { 
    //first save current array to localstorage - wasn't reliable anywhere else 
    localStorage.setItem("_shoesandsocks_recipes", JSON.stringify(this.state.recipeArray)); 

    //render page 
    return (
     <div className="App"> 
     <div className="recipeContainer"> 
      // etc etc 

私はこれが狂ったデザインだと知っていますが、動作します。

+0

あなたのやり方を試してみましたが、残念ながら私は同じことに気付きました。あなたの答えを試してみましたが、私はまだ15ポイントに達していません:/ –

+0

親コンポーネントとlocalstorageの状態は正しく変更されていますが、何らかの理由で間違ったコンポーネントが削除されています。たぶん、状態は子供に渡されると壊れている - しかし、私はどのように理解できません。 –

+0

レシピのリストを繰り返しているときに、キーが見つからないという警告が表示されますか?私はあなたのコードを私が作業しているサンプルアプリケーションの別のページに引っ張ってみましたが、私はすべての方法で作業していませんでした(私はブートストラップを持っていません)レシピデータ 'をあなたのアプリに従わせて、それをページにレンダリングします。コンソールでは、キーに関する警告が表示されます。キーを持っていないと、どのオブジェクトが削除される可能性がありますか? [キーのReact docsを参照](https://facebook.github.io/react/docs/lists-and-keys.html#keys) –

関連する問題