2017-12-04 4 views
0

siteEdit.jsというコンテナを作成しました。これは、 "サイト"の編集&の作成を処理します。reduxを使用してフォーム入力を編集できません

私はフォームデータの取得とAPIへの送信を処理するactionCreatorsをセットアップしました。これは完全に機能します。

IDを含むルートを使用してコンテナにアクセスすると、idパラメータに基づいて「サイト」データを取得するactionCreatorが実行されます。

これはすべて正常に動作しますが、私はreduxを使用しているので、私は小道具で入力値を設定しています。たとえば、this.props.title

私は今のところredux-formパッケージを使用しないようにしています。

コンテナ:

import React, {Component} from 'react'; 
import { connect } from 'react-redux'; 

import {createSite, getSite} from '../../actions/siteActions'; 

class SiteEdit extends Component { 
    constructor(props) { 
    super(props) 
    this.state = { 
     title: '', 
     url: '', 
     description: '', 
     approvedUsers: [] 
    } 
    this.handleSubmit = this.handleSubmit.bind(this) 
    this.handleInputChange = this.handleInputChange.bind(this) 
    } 

    componentWillMount() { 
    if(this.props.params.id) { 
     this.props.dispatch(getSite(this.props.params.id)) 
    } 
    } 



    handleInputChange(e) { 
    const target = e.target 
    const value = target.type === 'checkbox' ? target.checked : target.value 
    const name = target.name 

    this.setState({ 
     [name]: value 
    }) 
    } 

    handleSubmit(e) { 
    e.preventDefault() 
    this.props.dispatch(createSite(this.state)) 
    } 

    render() { 

    const {title, url, description, approvedUsers} = this.props 

    return (
     <div className="SiteEdit"> 
     <h1>NEW SITE</h1> 
     <form onSubmit={this.handleSubmit}> 

      <div className="block"> 
      <label>Site Name</label> 
      <input 
       className="input" 
       type="text" 
       value={title ? title : this.state.title} 
       onChange={this.handleInputChange} 
       name="title" /> 
      </div> 
      <div className="block"> 
      <label>Site URL</label> 
      <input 
       className="input" 
       type="text" 
       value={this.state.url} 
       onChange={this.handleInputChange} 
       name="url" /> 
      </div> 
      <div className="block"> 
      <label>Description</label> 
      <input 
       className="textarea" 
       type="textarea" 
       value={this.state.description} 
       onChange={this.handleInputChange} 
       name="description" /> 
      </div> 
      <div className="block"> 
      <label>Approved Users</label> 
      <input 
       className="input" 
       type="text" 
       value={this.state.approvedUsers} 
       onChange={this.handleInputChange} 
       name="approvedUsers" /> 
      </div> 

      <button className="button--action">Create</button> 
     </form> 
     </div> 
    ) 
    } 
} 

const mapStateToProps = (state) => ({ 
    title: state.sites.showSite.title, 
    url: state.sites.showSite.url, 
    description: state.sites.showSite.description, 
    approvedUsers: state.sites.showSite.approvedUsers 
}) 

SiteEdit = connect(mapStateToProps)(SiteEdit) 

export default SiteEdit 

ActionCreators:

import config from '../config' 
import { push } from 'react-router-redux' 


const apiUrl = config.api.url 

// List all sites 
export const LIST_SITES_START = 'LIST_SITES_START' 
export const LIST_SITES_SUCCESS = 'LIST_SITES_SUCCES' 
export const LIST_SITES_ERROR = 'LIST_SITES_ERROR' 

export function sitesListStart(data) { 
    return { type: LIST_SITES_START, data } 
} 

export function sitesListSuccess(data) { 
    return { type: LIST_SITES_SUCCESS, data } 
} 

export function sitesListError(data) { 
    return { type: LIST_SITES_ERROR, data } 
} 

export function listSites() { 
    return (dispatch) => { 
    dispatch(sitesListStart()) 
    fetch(`${apiUrl}/listSites`) 
    .then(res => res.json()) 
    .then(json => { 
     dispatch(sitesListSuccess(json)) 
    }) 
    .catch(error => { 
     dispatch(sitesListError) 
    }) 
    } 
} 

// Create & Edit Sites 
export const CREATE_SITE_START = 'CREATE_SITE_START' 
export const CREATE_SITE_SUCESS = 'CREATE_SITE_SUCCESS' 
export const CREATE_SITE_ERROR = 'CREATE_SITE_ERROR' 

export function siteCreateStart(data) { 
    return { type: CREATE_SITE_START, data} 
} 

export function siteCreateSuccess(data) { 
    return { type: CREATE_SITE_SUCCESS, data} 
} 

export function siteCreateError(error) { 
    return { type: CREATE_SITE_ERROR, error} 
} 

export function createSite(data) { 
    return (dispatch) => { 
    dispatch(siteCreateStart()) 
    fetch(`${apiUrl}/createSite`, { 
     method: 'post', 
     headers: { 
     Accept: 'application/json', 
     'Content-Type': 'application/json' 
     }, 
     body: JSON.stringify(data) 
    }) 
    .then(res => res.json()) 
    .then(json => { 
     dispatch(push('/')) 
     dispatch(siteCreateSuccess()) 
    }) 
    .catch(error => { 
     dispatch(siteCreateError()) 
    }) 

    } 
} 

// Get Single Site 
export const GET_SITE_START = 'GET_SITE_START' 
export const GET_SITE_SUCCESS = 'GET_SITE_SUCCESS' 
export const GET_SITE_ERROR = 'GET_SITE_ERROR' 

export function getSiteStart(data) { 
    return { type: GET_SITE_START, data} 
} 

export function getSiteSuccess(data) { 
    return { type: GET_SITE_SUCCESS, data} 
} 

export function getSiteError(error) { 
    return { type: GET_SITE_ERROR, error} 
} 

export function getSite(id) { 
    return (dispatch) => { 
    dispatch(getSiteStart()) 
    fetch(`${apiUrl}/getSite/${id}`) 
    .then(res => res.json()) 
    .then(json => { 
     dispatch(getSiteSuccess(json)) 
    }) 
    .catch(error => { 
     dispatch(getSiteError()) 
    }) 
    } 
} 

リデューサー:

import {push} from 'react-router-redux' 
import { 
    LIST_SITES_START, 
    LIST_SITES_SUCCESS, 
    LIST_SITES_ERROR, 
    GET_SITE_START, 
    GET_SITE_SUCCESS, 
    GET_SITE_ERROR 
} from '../actions/siteActions' 

const initialState = { 
    sitesList: { 
    sites: [], 
    error: null, 
    loading: true 
    }, 
    showSite: { 
    title: '', 
    url: '', 
    description: '', 
    approvedUsers: [], 
    loading: true 
    } 
} 

export default function (state = initialState, action) { 
    switch (action.type) { 
    // List Sites 
    case LIST_SITES_START: 
     return Object.assign({}, state, { 
     sitesList: Object.assign({}, state.sitesList, { 
      loading: true 
     }) 
     }) 
    case LIST_SITES_SUCCESS: 
     return Object.assign({}, state, { 
     sitesList: Object.assign({}, state.sitesList, { 
      sites: action.data, 
      loading: false 
     }) 
     }) 
    case LIST_SITES_ERROR: 
     return Object.assign({}, state, { 
     error: action.error, 
     loading: false 
     }) 

    case GET_SITE_START: 
     return Object.assign({}, state, { 
     showSite: Object.assign({}, state.showSite, { 
      loading: true 
     }) 
     }) 
    case GET_SITE_SUCCESS: 
     return Object.assign({}, state, { 
     showSite: Object.assign({}, state.showSite, { 
      ...action.data, 
      loading: false 
     }) 
     }) 
    case GET_SITE_ERROR: 
     return Object.assign({}, state, { 
     showSite: Object.assign({}, state.showSite, { 
      error: action.error, 
      loading: false 
     }) 
     }) 

    default: 
     return state 
    } 
} 
+0

あなたは問題が何であるかを明確にすることができますか、私はあなたがここで何を求めているかを本当に伝えることはできませんか?問題に関連しないコードの一部を削除しても問題が解決する可能性があります。 – ajmajmajma

+0

@ajmajmajma問題はこのコード行です。 '' '< className =" input " type =" text " value = {タイトル?タイトル:this.state.title} onChange = {this。handleInputChange} name = "title" /> '' 'this.props.title'の値で、状態を更新させません。私は小道具から州を設定する必要があると思いますか? – Dileet

+0

私は以下の答えを追加しました。将来的には、問題が数行しかない場合には、それほど多くのコードを追加する必要はありません。幸運〜 – ajmajmajma

答えて

1

あなたは敷石です

const { title } = this.props; 
... 
value={title ? title : this.state.title} 

あなたonChangeロジック正しいか、おそらく正しくコンポーネントのローカル状態を更新している、しかし、あなたはまだthis.propsを持っている - これだけに再反復は次のように、props.title取っ先例と価値のために三元をする。タイトルは、その三元語に先行しています。

これを処理できる方法はたくさんありますが、実際には操作の順序に依存します(つまり、props.titleが真実であるかどうか)。コンポーネントは、あなたのようなコンストラクタで何かを行うことができますマウントするときにタイトルを持っていると仮定すると:

constructor(props) { 
    super(props) 
    this.state = { 
     title: props.title, << set default here 
     url: '', 
     description: '', 
     approvedUsers: [] 
    } 

は、入力中にあなただけのこれが異なります状態のタイトル

value={this.state.title} 

に値を設定する必要がありますもちろん、あなたのコンポーネントにprops.titleの値が入ったときに、マウントのためにそこになければ、これは意図したとおりには動作しません。

また、入力の値についてもこのすべてを評価する関数を渡すことができます。その内部で、props.titleとstate.titleをより冗長にチェックし、値として返す値を決定します。

<input value={this.returnTitleValue} .. << something like so 

これが役に立ちます。

+1

詳細な答えをありがとう。これは多くの助けとなりました。問題は今、私は状態を埋めるためにそれを2回ルートに移動する必要があります。それは理にかなっていますか?以前経験したことがありますか? – Dileet

関連する問題