2017-03-12 11 views
10

を反応させるのチュートリアルをReactJS:React.js Introduction For People Who Know Just Enough jQuery To Get Byは、エラー「既存の状態遷移時に更新できません。」私は、このステップ15をやろうとしている

著者は次のことをお勧めします。

overflowAlert: function() { 
    if (this.remainingCharacters() < 0) { 
    return (
     <div className="alert alert-warning"> 
     <strong>Oops! Too Long:</strong> 
     </div> 
    ); 
    } else { 
    return ""; 
    } 
}, 

render() { 
    ... 

    { this.overflowAlert() } 

    ... 
} 

私がやってみました(私には大丈夫に見えた)次

// initialized "warnText" inside "getInitialState" 


overflowAlert: function() { 
    if (this.remainingCharacters() < 0) { 
    this.setState({ warnText: "Oops! Too Long:" }); 
    } else { 
    this.setState({ warnText: "" }); 
    } 
}, 

render() { 
    ... 

    { this.overflowAlert() } 
    <div>{this.state.warnText}</div> 

    ... 
} 

そして私はクローム開発ツールでコンソールに次のエラーを受け取った:

既存の状態遷移中に更新できません(renderまたは他のコンポーネントのコンストラクタ内など)。レンダリング方法は、小道具と国家の純粋な機能である でなければなりません。コンストラクタの副作用は パターンですが、componentWillMountに移動することができます。

ここにはJSbin demoがあります。なぜ私のソリューションは動作しませんし、このエラーはどういう意味ですか?

+3

考えてみましょう:状態が更新されるとコンポーネントが再レンダリングされるので、レンダリングメソッドで状態を更新すると無限ループになります。ここで何を達成しようとしていますか?誰かがテキストなどを入力するたびに状態を更新します。 – Li357

+0

@AndrewLi Lucid答え。先に進んで答えとして提出すれば、正しいとマークします。私はここで達成しようとしているもの:私は解決策を見ずに私自身のやり方をしようとしていた、これは私が思いついたものでした。 –

答えて

17

あなたのソリューションは論理的に意味をなさないので機能します。あなたが受け取ったエラーは多少曖昧かもしれないので、私はそれを分解してみましょう。最初の行の状態は次のようになります。

(レンダリングや他のコンポーネントのコンストラクタ内など)既存の状態遷移中は更新できません。

リアクションコンポーネントの状態が更新されるたびに、コンポーネントはDOMに再レンダリングされます。この場合、overflowAlertrenderにコールしようとしていますが、これはsetStateを呼び出しているため、エラーが発生しています。つまり、レンダリングで状態を更新しようとしています。レンダリングではoverflowAlertを呼び出し、ステートを更新してレンダリングを再描画し、無限ループになります。このエラーは、最初に状態を更新した結果として状態を更新しようとしていることを伝え、ループにつながります。これが許されない理由です。

代わりに、別のアプローチをとり、達成しようとしていることを覚えておいてください。ユーザーがテキストを入力するときに警告を表示しようとしていますか?そのような場合は、入力のイベントハンドラとしてoverflowAlertを設定します。これにより、入力イベントが発生したときに状態が更新され、コンポーネントが再レンダリングされます。

0

レンダリングメソッドのコンポーネントに関連するタスクの代わりに、コンポーネントの更新後に行います。 この場合、スプラッシュ画面から別の画面への移動は、componentDidMountメソッド呼び出しの後にのみ実行されます。

import React, { Component } from 'react'; 
import { 
StyleSheet, 
Text, 
View, 
Button, 
Image, 
} from 'react-native'; 


let timeoutid; 

export default class Splash extends Component { 

static navigationOptions = { 
navbarHidden: true, 
tabBarHidden: true, 
}; 

constructor(props) { 
super(props) 
this.state = { navigatenow: false }; 

} 
componentDidMount() { 
timeoutid=setTimeout(() => { 
    this.setState({ navigatenow: true }); 
}, 5000); 
} 
componentWillUnmount(){ 

clearTimeout(timeoutid); 
} 
componentDidUpdate(){ 
const { navigate,goBack } = this.props.navigation; 

if (this.state.navigatenow == true) { 

    navigate('Main'); 
} 
} 
render() { 

//instead of writing this code in render write this code in 
componenetDidUdpate method 
/* const { navigate,goBack } = this.props.navigation; 

if (this.state.navigatenow == true) { 

    navigate('Main'); 
}*/ 

return (

    <Image style={{ 
    flex: 1, width: null, 
    height: null, 
    resizeMode: 'cover' 
    }} source={require('./login.png')}> 
    </Image> 
); 

    } 
} 
0

正しい表現を使用していることを確認してください。例えば、使用:

<View onPress={this.props.navigation.navigate('Page1')} /> 

又は

<View onPress={() => { 
    this.props.navigation.navigate('Page1') 
}} /> 

最後の二つ上である機能発現と異なり、最初のものではありません。関数オブジェクトを関数式に渡していることを確認してください() => {}

関連する問題