2017-01-31 7 views
0

このコンポーネントはあります。それは小道具を受け取り、componentWillReceiveProps私はそれらの小道具を何らかの形の詳細を記入するための州として設定しました。そして、私は手動でこのようなURLを入力すると動作しますhttp://localhost:3000/dashboard/emailpreview/SKXj7t86agAzmRefG 素晴らしいです!しかし、そのURLを指す反応ルータのリンクをクリックすると、componentWillReceivePropsはまったくトリガーされないので、フォームフィールドはあらかじめ埋め込まれていません。しかし、もう一度手動リフレッシュを実行すると、すべてが機能します。なぜこれが起こるのですか?どうしたの? LinkcomponentWillReceivePropsがトリガーされないのはなぜですか?react-routerでcomponentWillReceivePropsがトリガーされないリンク

import React, { Component } from 'react' 
import { browserHistory } from 'react-router' 
import { Editor } from 'react-draft-wysiwyg' 
import { convertToRaw } from 'draft-js' 
import { createContainer } from 'meteor/react-meteor-data' 
import { Emails } from '../../../../../imports/collections/emails/Emails' 
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' 
import draftToHtml from 'draftjs-to-html' 
import { stateFromHTML } from 'draft-js-import-html' 
import _ from 'lodash' 

class EmailEditor extends Component { 
    constructor (props) { 
    super(props) 
    this.state = { 
     name: '', 
     to: '', 
     subject: '', 
     html: '', 
     error: '' 
    } 
    } 

// TODO: If there is id then fill in the information 
     // TODO: Subscribe and find and fill in with state 
    componentWillReceiveProps (nextProps) { 
    console.log('acsdcdsc', nextProps.email.name) 
    this.setState({name: nextProps.email.name, to: nextProps.email.to, subject: nextProps.email.subject}) 
    } 
    handleChange (event) { 
    const changedOne = event.target.name 
    const newValue = event.target.value 
    const newState = {} 
    newState[changedOne] = newValue 
    this.setState(newState) 
    } 
    saveEmail() { 
    const self = this 
    console.log('saveEmail') 
    const { emailId } = this.props.params 
    console.log(emailId) 
    console.log('email') 
    const { name, to, subject, attachments, editorState } = this.state 
    console.log('editorState', editorState) 
    if (_.isEmpty(editorState)) { 
     self.setState({error: 'Please fill requaired fields'}) 
     return 
    } 
    const rawContentState = convertToRaw(editorState.getCurrentContent()) 
    const html = draftToHtml(rawContentState) 
    console.log('html', html) 
    const email = { 
     emailId, 
     name, 
     to, 
     subject, 
     html, 
     attachments // TODO: figure out how to send this 
    } 
    if (emailId === 'new') { 
     Meteor.call('emails.insert', email, (err, emailId) => { 
     if (err) { 
      self.setState({error: 'Please fill requaired fields'}) 
      return 
     } 
     if (emailId) console.log(emailId) 
     browserHistory.push(`/dashboard/emailpreview/${emailId}`) 
     }) 
    } else { 
     Meteor.call('emails.update', email, (err, emailId) => { 
     if (err) console.log(err) 
     if (emailId) console.log(emailId) 
     browserHistory.push(`/dashboard/emailpreview/${emailId}`) 
     }) 
    } 
    } 
    renderEditor() { 
    return(
     <div className="form-group"> 
      <div><label style={{display: 'block', color: 'red', marginBottom: '10px'}}>*</label><input value={this.state.name} onChange={this.handleChange.bind(this)} type="text" name="name" placeholder="Email Name" /></div> 
      <div><label style={{display: 'block', color: 'red', marginBottom: '10px'}}>*</label><input value={this.state.to} onChange={this.handleChange.bind(this)} type="text" name="to" placeholder="To" /></div> 
      <div><label style={{display: 'block', color: 'red', marginBottom: '10px'}}>*</label><input value={this.state.subject} onChange={this.handleChange.bind(this)} type="text" name="subject" placeholder="Subject" /></div> 
      <div><span style={{display: 'block', color: 'red', margin: '10px'}}>{this.state.error}</span></div> 
      <Editor 
      toolbarClassName="wysiwig-toolbar" 
      wrapperClassName="wysiwig-wrapper" 
      editorClassName="wysiwig-editor" 
      onEditorStateChange={(editorState) => { 
       this.setState({ 
       editorState 
       }) 
       console.log(editorState) 
      }} 
      /> 
      <button onClick={this.saveEmail.bind(this)} className="btn btn-success">Save</button> 
      <button className="btn btn-primary">Send</button> 
      <button className="btn btn-primary">Test</button> 
     </div> 
    ) 
    } 
    render() { 
    console.log('listItems1010', this.state) 
    console.log('listItems prop11010', this.props.email) 
    return (
     <div className="EmailEditor"> 
     {this.renderEditor()} 
     </div> 
    ) 
    } 
} 
// https://jpuri.github.io/react-draft-wysiwyg/#/docs?_k=jjqinp 
// {/* editorState={editorState} 
// toolbarClassName="home-toolbar" 
// wrapperClassName="home-wrapper" 
// editorClassName="home-editor" 
// onEditorStateChange={this.onEditorStateChange} 
// uploadCallback={uploadImageCallBack} */} 
export default createContainer((props) => { 
    const {emailId} = props.params 
    Meteor.subscribe('emails') 
    return {email: Emails.findOne(emailId)} 
}, EmailEditor) 

答えて

0

問題は、初期レンダリングでcomponentWillReceivePropsが呼び出されないことです。ライフサイクルメソッドに関するドキュメントを読んで、完全に理解してください。http://reactjs.cn/react/docs/component-specs.html#lifecycle-methods

問題を解決するためにコンストラクタで状態を設定するだけです。

constructor (props) { 
    super(props) 
    this.state = { 
    name: props.name, 
    to: props.email.to, 
    subject: props.email.subject, 
    html: '', 
    error: '' 
    } 
} 

このコードは、より完全なソリューションがこれに似たもので、未定義のエラーを避けるためだろう、しかし、いくつかの未定義エラーが発生することがあります。

constructor (props) { 
    super(props) 
    const { email, name } = props; 
    this.state = { 
    name, 
    to: email && email.to, 
    subject: email && email.subject, 
    html: '', 
    error: '' 
    } 
} 
+1

ようになり、この

componentDidMount() { if (this.props.email) { this.setState({ name: this.props.email.name, to: this.props.email.to, subject: this.props.email.subject, html: this.props.email.html, editorState: EditorState.createWithContent(stateFromHTML(this.props.email.html)) }) } } 

ように私は、例えばcomponentDidMountを使用レンダリング初期のsetStateへので、私はこの方法で、以前試みたが、私が得るすべては、私の値として定義されていません。 –

0

それが最初のレンダリング時にトリガされないcomponentWillReceivePropsが判明したように。コンポーネントの更新時にのみトリガされます。だから、最終的なコードが

import React, { Component } from 'react' 
import { browserHistory } from 'react-router' 
import { Editor } from 'react-draft-wysiwyg' 
import { convertToRaw, EditorState } from 'draft-js' 
import { createContainer } from 'meteor/react-meteor-data' 
import { Emails } from '../../../../../imports/collections/emails/Emails' 
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' 
import draftToHtml from 'draftjs-to-html' 
import { stateFromHTML } from 'draft-js-import-html' 
import _ from 'lodash' 

class EmailEditor extends Component { 
    constructor (props) { 
    super(props) 
    this.state = { 
     name: '', 
     to: '', 
     subject: '', 
     html: '', 
     error: '', 
     editorState: EditorState.createEmpty() 
    } 
    } 

    componentWillReceiveProps (nextProps, nextContext) { 
    console.log('componentWillReceiveProps nextProps.email.name', nextProps.email.name) 
    this.setState({ 
     name: nextProps.email.name, 
     to: nextProps.email.to, 
     subject: nextProps.email.subject, 
     html: nextProps.email.html, 
     editorState: EditorState.createWithContent(stateFromHTML(nextProps.email.html)) 
    }) 
    } 
    componentDidMount() { 
    if (this.props.email) { 
     this.setState({ 
     name: this.props.email.name, 
     to: this.props.email.to, 
     subject: this.props.email.subject, 
     html: this.props.email.html, 
     editorState: EditorState.createWithContent(stateFromHTML(this.props.email.html)) 
     }) 
    } 
    } 
    handleChange (event) { 
    const changedOne = event.target.name 
    const newValue = event.target.value 
    const newState = {} 
    newState[changedOne] = newValue 
    this.setState(newState) 
    } 
    saveEmail() { 
    const self = this 
    console.log('saveEmail') 
    const { emailId } = this.props.params 
    console.log(emailId) 
    console.log('email') 
    const { name, to, subject, attachments, editorState } = this.state 
    console.log('editorState', editorState) 
    if (_.isEmpty(editorState)) { 
     self.setState({error: 'Please fill requaired fields'}) 
     return 
    } 
    const rawContentState = convertToRaw(editorState.getCurrentContent()) 
    const html = draftToHtml(rawContentState) 
    console.log('html', html) 
    const email = { 
     emailId, 
     name, 
     to, 
     subject, 
     html, 
     attachments // TODO: figure out how to send this 
    } 
    if (emailId === 'new') { 
     Meteor.call('emails.insert', email, (err, emailId) => { 
     if (err) { 
      self.setState({error: 'Please fill requaired fields'}) 
      return 
     } 
     if (emailId) console.log(emailId) 
     browserHistory.push(`/dashboard/emailpreview/${emailId}`) 
     }) 
    } else { 
     Meteor.call('emails.update', email, (err, result) => { 
     if (err) console.log(err) 
     if (result) console.log('update result', result) 
     browserHistory.push(`/dashboard/emailpreview/${emailId}`) 
     }) 
    } 
    } 
    renderEditor() { 
    return (
     <div className="form-group"> 
     <div><label style={{display: 'block', color: 'red', marginBottom: '10px'}}>*</label><input 
      value={this.state.name} 
      onChange={this.handleChange.bind(this)} 
      type="text" 
      name="name" 
      placeholder="Email Name" /></div> 
     <div><label style={{display: 'block', color: 'red', marginBottom: '10px'}}>*</label><input 
      value={this.state.to} 
      onChange={this.handleChange.bind(this)} 
      type="text" 
      name="to" 
      placeholder="To" /></div> 
     <div><label style={{display: 'block', color: 'red', marginBottom: '10px'}}>*</label><input 
      value={this.state.subject} 
      onChange={this.handleChange.bind(this)} 
      type="text" 
      name="subject" 
      placeholder="Subject" /></div> 
     <div><span style={{display: 'block', color: 'red', margin: '10px'}}>{this.state.error}</span></div> 
     <Editor 
      editorState={this.state.editorState} 
      toolbarClassName="wysiwig-toolbar" 
      wrapperClassName="wysiwig-wrapper" 
      editorClassName="wysiwig-editor" 
      onEditorStateChange={(editorState) => { 
      this.setState({ 
       editorState 
      }) 
      console.log('editorState', editorState) 
      console.log('this.state', this.state) 
      }} 
     /> 
     <button onClick={this.saveEmail.bind(this)} className="btn btn-success">Save</button> 
     <button className="btn btn-primary">Send</button> 
     <button className="btn btn-primary">Test</button> 
     </div> 
    ) 
    } 
    render() { 
    console.log('render state', this.state) 
    console.log('render props email', this.props.email) 
    return (
     <div className="EmailEditor"> 
     {this.renderEditor()} 
     </div> 
    ) 
    } 
} 
// https://jpuri.github.io/react-draft-wysiwyg/#/docs?_k=jjqinp 
// {/* editorState={editorState} 
// toolbarClassName="home-toolbar" 
// wrapperClassName="home-wrapper" 
// editorClassName="home-editor" 
// onEditorStateChange={this.onEditorStateChange} 
// uploadCallback={uploadImageCallBack} */} 

export default createContainer((props) => { 
    const {emailId} = props.params 
    Meteor.subscribe('emails') 
    return {email: Emails.findOne(emailId)} 
}, EmailEditor) 
関連する問題