2016-12-28 9 views
0

私は、配列からブックのリストをレンダリングし、別のブックオブジェクトを配列にプッシュするフォームを持つ、基本的なReactアプリケーションを構築しています。私は本の配列を変更することはPostコンポーネントを再レンダリングさせる原因となる小道具への変更だと思っていましたが、私はリンクをしっかりと動かすことによって手動で強制しない限り、Postを再レンダリングすることはできません。私は書籍の配列だけでなく関連するすべてのコンポーネントを添付していると思います。私は、React環境をセットアップするためにcreate-react-appを使用しました。 反応バージョン - 15.4.1。何かお手伝いいただきありがとうございました!基本的なReactアプリケーションでのコンポーネントの再レンダリングに関する問題

編集: 私は少しをリファクタリングし、すべてがより明確にするためにgithubのレポを作成しました。

Github Repo

import React from 'react' 
 
import ReactDOM from 'react-dom' 
 
import {Router, Route, IndexRoute, hashHistory} from 'react-router' 
 

 
import App from './App' 
 
import Display from './Display' 
 
import Content from './Content' 
 

 
//stylesheet 
 
import './index.css' 
 

 
//import posts array 
 
import postsArray from './postsArray' 
 

 
ReactDOM.render(
 
    <Router history={hashHistory}> 
 
    <Route path="/" component={App}> 
 
     <IndexRoute component={Display} entries={postsArray}></IndexRoute> 
 
     <Route path="view/:id" component={Content} entries={postsArray}></Route> 
 
    </Route> 
 
    </Router>, 
 
    document.getElementById('root') 
 
);

import React, {Component} from 'react' 
 

 
import Post from './Post' 
 

 

 
class Display extends Component { 
 

 
    constructor(props) { 
 
    super(props) 
 
    this.handleSubmit = this.handleSubmit.bind(this) 
 
    } 
 

 
    handleSubmit(event) { 
 
    this.props.route.entries.push({ 
 
     title: this.titleInput.value, 
 
     author: this.authorInput.value, 
 
     body: this.bodyText.value 
 
    }) 
 
    event.preventDefault() 
 
    } 
 

 

 
    render() { 
 
    return(
 
     <div> 
 
     <Post entries={this.props.route.entries}/><br /> <br /> 
 
     <form onSubmit={this.handleSubmit}> 
 
      <label> 
 
      Title:<br /> 
 
      <input type={"text"} ref={(titleInput) => this.titleInput = titleInput} className="input" /> 
 
      </label><br /> 
 
      <label> 
 
      Author:<br /> 
 
      <input type="text" ref={(authorInput) => this.authorInput = authorInput} className="input" /> 
 
      </label> <br /> 
 
      <label> 
 
      Body:<br /> 
 
      <textarea ref={(bodyText) => this.bodyText = bodyText} className="textAreaInput"/> 
 
      </label> <br /> 
 
      <input type="submit" value="Submit" /> 
 
     </form> 
 
     </div> 
 
    ) 
 
    } 
 
} 
 

 
export default Display

import React, {Component} from 'react' 
 
import {Link} from 'react-router' 
 

 

 
class Post extends Component { 
 
    constructor(props) { 
 
    super(props) 
 
    console.log("insinde post initial", this.props.entries) 
 
    } 
 
    render() { 
 
    return (
 
     <div className="postsWrapper"> 
 
     {this.props.entries.map((entry, index) => (
 
      <div key={index} className="divMargin"> 
 
      <Link to={"view/" + index } className="postLink"> 
 
       <h1 className="postH titleFont">{entry.title}</h1> 
 
       <h2 className="authorFont authorMargin">{entry.author}</h2> 
 
      </Link> 
 
      </div> 
 
     ))} 
 
     </div> 
 
    ) 
 
    } 
 
} 
 

 
export default Post
0123デフォルトでは

+0

ルーターでの「エントリ」の使用は私には珍しいようです。あなたはなぜこのようにポスト配列を配置したいのかをさらに説明できますか? –

+0

そして、あなたはポスト配列をロギングしているので、ポストコンポーネントで配列小道具を正常に更新できますか? –

+0

私はルータから小道具として配列を渡すことを任意に決めました。それは最善の決定ではないかもしれませんが、私がディスプレイコンポーネントから小道具としてエントリーを渡しても、私は同じ問題を抱えます。また、Postコンポーネントは実際には各Postのレンダリングだけを担当しており、更新が行われたフォームからは切り離されていますが、その変更が原因でまだ再レンダリングする必要があります。 –

答えて

0

してみてください。最終的な解決策は、次のようなものでした:

this.setState({ 
    entries: this.state.entries.concat([{ 
    title: this.titleInput.value, 
    author: this.authorInput.value, 
    body: this.bodyText.value 
    }]) 
}) 

実際の変更は興味があればgithubリポジトリにあります。

@Stanley Luoがデバッグに手伝ってくれてくれてありがとう。

1

、小道具(あなたのケースでは、ポスト・アレイ)変更した場合は、関連するコンポーネントは問題なく更新する必要があります。

あなたのPostコンポーネントが更新を拒否しているため、shouldComponentUpdate()を使用して、小道具が適切に更新されているかどうかを点検することをおすすめします。

shouldComponentUpdateは常にレンダリングメソッドの前に呼び出され、再レンダリングが必要かスキップするかを定義することができます。

componentWillUpdateは、shouldComponentUpdateがtrueを返すとすぐに呼び出されます。 this.setStateによる状態変更は許可されません。このメソッドは、更新自体をトリガーしない次回の更新を準備するために厳密に使用する必要があるためです。

ライフサイクルの方法に精通していない場合は、articleにチェックを入れてください。

お使いの場合には

、私はsetState.concatを使用しての代わり.pushと直接配列を変異することにより(何かを学ぶ)この問題を解決することができました

shouldComponentUpdate(nextProps, nextState) { 
    return nextProps.entries.length !== this.props.entries.length; 
} 

componentWillUpdate(nextProps, nextState) { 
    // posts array did change, do something 
} 
+0

助けてくれてありがとう!私は、再レンダリングをトリガーしなかったshouldComponentUpdateメソッドを実装しようとしました。私はreturnの上にconsole.logを置くだけで呼び出されていたのですが、shouldComponentUpdateが呼び出されなかったかのように何も取得できませんでした。 –

+0

@HarryZumwaltつまり、あなたの小道具や州が変更されていないことを意味します。あなたがルーターを通過した小道具はそれに応じて更新されていない可能性が高いです。 posts配列を得るための新しい方法を試してください。 'componentWillMount()'ライフサイクルメソッドを使って 'Redux store'から配列を取得することをお勧めします。 –

+0

興味深いことに私はすでに 'Display'(ルーターではない)経由で直接小道具を持ってきてみました。私はまた、コンストラクタ/ componentWillMountフック内の配列と同じ状態を成功と一緒に設定しようとしました。私はReduxが必要ではないと確信しています。これで困った。 –

関連する問題