2017-12-05 27 views
1

リアクションコンポーネントのコンストラクターが2回呼び出されていますが、理由がわかりません。私は私のアプリの言語を格納するためにreact-reduxを使用しています。私はブラウザの言語でデフォルトの言語ベースを設定する関数を持っています。 LoginPageはレンダリングされる最初のコンポーネントなので、私はそのコンストラクタで自分の関数を呼び出しました。基本的には、アクションを比較してディスパッチすることです。私がreduxデベロッパーツールで私の状態をチェックしたとき、私はそれが2回ディスパッチされているのを見た。私はコンストラクタにダミーデータを印刷し、それも2回印刷されます。コンストラクターが2回呼び出されました。リアクションコンポーネント

LoginPage.js

import React from 'react'; 
import {connect} from 'react-redux'; 
import {startLogin} from '../actions/auth'; 
import {setLanguage} from '../actions/lang'; 

export class LoginPage extends React.Component{ 

    constructor(props){ 
    super(props); 
    this.setDefaultLanguage(); 
    console.log('i am constructor'); 
    } 

    changeLanguage = (e) => { 
    const lan = e.target.value; 
    this.props.setLanguage(lan); 
    }; 

    setDefaultLanguage =() => { 
    const defaultLanguage = navigator.language || navigator.userLanguage || 'en-US'; 

    if(defaultLanguage == 'es'){ 
     this.props.setLanguage(defaultLanguage); 
    }else{ 
     this.props.setLanguage('en'); 
    } 
    } 

    render(){ 
    return(
     <div className="box-layout"> 
     <div className="box-layout__box"> 
      <h1 className="box-layout__title">Expensify</h1> 
      <p>It\'s time to get your expenses under control.</p> 
      <button className="button" onClick={this.props.startLogin}>Log in with google</button> 
      <select className="select" onChange={this.changeLanguage}> 
      <option value="en">English</option> 
      <option value="es">Español</option> 
      </select> 
     </div> 
     </div> 
    ) 
    }; 
} 

const mapDispatchToProps = (dispatch) => ({ 
    startLogin:() => dispatch(startLogin()), 
    setLanguage: (language) => dispatch(setLanguage(language)) 
}); 

export default connect(undefined, mapDispatchToProps)(LoginPage); 

App.js

import React from 'react'; 
import ReactDom from 'react-dom'; 
import {Router, Route, Switch} from 'react-router-dom'; 
import createHistory from 'history/createBrowserHistory'; 
import ExpenseDashBoardPage from '../components/ExpenseDashBoardPage'; 
import AddExpensePage from '../components/AddExpensePage'; 
import EditExpensePage from '../components/EditExpensePage'; 
import NotFoundPage from '../components/NotFoundPage'; 
import LoginPage from '../components/LoginPage'; 
import PrivateRoute from './PrivateRoute'; 
import PublicRoute from './PublicRoute'; 

export const history = createHistory(); 

const AppRouter =() => (
    <Router history={history}> 
    <div> 
     <Switch> 
     <PublicRoute path="/" component={LoginPage} exact={true} /> 
     <PrivateRoute path="/dashboard" component={ExpenseDashBoardPage} /> 
     <PrivateRoute path="/create" component={AddExpensePage} /> 
     <PrivateRoute path="/edit/:id" component={EditExpensePage} /> 
     <Route component={NotFoundPage} /> 
     </Switch> 
    </div> 

    </Router> 
) 

export default AppRouter; 

答えて

1

あなたはそれ自体でconnect(App)のようなものだけでなく、Appが表示されますレンダリングされているものの開発ツールに反応チェックした場合は、そのconsole.logが2回呼び出されます。これは、connectが上位コンポーネントであるためです。

this.setDefaultLanguage()(および実際に動作確認できるようにconsole.log)をコンストラクタの外からライフサイクルフックcomponentDidMountに移動すると、問題が解決するはずです。

1

まず、コンストラクタ内からReduxアクションやあらゆる種類のAJAXを呼び出すべきではありません。これらの作業はcomponentDidMount()で行う必要があります。

第2に、私は小道具の一部として店舗から言語を要求します。定義されていない場合はcomponentDidMount()setDefaultLanguage()とします。私は、少なくとも次のことを行うだろう

export class LoginPage extends React.Component { 
    componentDidMount() { 
    if (!this.props.lang) { 
     this.setDefaultLanguage(); 
    } 
    } 

    changeLanguage = (e) => { 
    const lan = e.target.value; 
    this.props.setLanguage(lan); 
    }; 

    setDefaultLanguage =() => { 
    const defaultLanguage = navigator.language || navigator.userLanguage || 'en-US'; 

    if(defaultLanguage == 'es'){ 
     this.props.setLanguage(defaultLanguage); 
    }else{ 
     this.props.setLanguage('en'); 
    } 
    } 

    render() { 
    return(
     <div className="box-layout"> 
     <div className="box-layout__box"> 
      <h1 className="box-layout__title">Expensify</h1> 
      <p>It\'s time to get your expenses under control.</p> 
      <button className="button" onClick={this.props.startLogin}>Log in with google</button> 
      <select className="select" onChange={this.changeLanguage}> 
      <option value="en">English</option> 
      <option value="es">Español</option> 
      </select> 
     </div> 
     </div> 
    ) 
    }; 
} 

const mapStateToProps = state => ({ 
    // Assuming `steate.lang` is where you would set the language. 
    lang: state.lang 
}); 

const mapDispatchToProps = (dispatch) => ({ 
    startLogin:() => dispatch(startLogin()), 
    setLanguage: (language) => dispatch(setLanguage(language)) 
}); 

const mergeProps = (stateProps, dispatchProps) => ({ ...stateProps, ...dispatchProps }); 

export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(LoginPage); 
+0

ありがとうございました。 「コンストラクタ内からReduxアクションやAJAXを呼び出さないでください」という文をサポートするためのソースを提供することができますか? –

+0

ええ、ここにリンクがあります:https://engineering.musefind.com/react-lifecycle-methods-how-and-to-use-them-them-2111a1b692b1、https://daveceddia.com/ajax-requests-in-react/、https://reactjs.org/docs/react- component.html#componentdidmount – Eye

1

私は私のパブリックルート内のユーザーをリダイレクトされたので、私は同じ問題を抱えていました。そのため、コンポーネントを2回レンダリングしていました。あなたが使用している場合

history.push('/'); 

これはコンポーネントを2回レンダリングする予定です。

関連する問題