2016-03-28 17 views
2

Ich lerne langsam Reagieren und lernen, es mit Redux zu implementieren. Aber ich habe anscheinend eine Straßensperre getroffen. Das ist also was ich bisher habe.Implementierung React Redux

/index.jsx

import './main.css' 
import React from 'react' 
import ReactDOM from 'react-dom' 
import App from './components/App.jsx' 
import { Provider } from 'react-redux' 
import { createStore } from 'redux' 
import ShoppingList from './reducers/reducer' 

let store = createStore(ShoppingList) 

ReactDOM.render(
    <Provider store={store}> 
    <App /> 
    </Provider>, 
    document.getElementById('app') 
) 

/actions/items.js

import uuid from 'node-uuid' 

export const CREATE_ITEM = 'CREATE_ITEM' 
export function createItem(item) { 
    return { 
    type: CREATE_ITEM, 
    item: { 
     id: uuid.v4(), 
     item, 
     checked: false 
    } 
    } 
} 

/reducers/reducer.js

import * as types from '../actions/items' 
import uuid from 'node-uuid' 

const initialState = [] 

const items = (state = initialState, action) => { 
    switch (action.type) { 
    case types.CREATE_ITEM: 
     return { 
     id: uuid.v4(), 
     ...item 
     } 
    default: 
     return state; 
    } 
} 

export default items 

/reducers/index.js
UPDATE :

import { combineReducers } from 'redux' 
import items from './reducer' 

const ShoppingList = combineReducers({ 
    items 
}) 

export default ShoppingList 

/components/Item.jsx

import React from 'react'; 
import uuid from 'node-uuid' 

export default class Item extends React.Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     isEditing: false 
    } 
    } 

    render() { 
    if(this.state.isEditing) { 
     return this.renderEdit(); 
    } 

    return this.renderItem(); 
    } 

    renderEdit =() => { 
    return (
     <input type="text" 
     ref={(event) => 
      (event ? event.selectionStart = this.props.text.length : null) 
     } 
     autoFocus={true} 
     defaultValue={this.props.text} 
     onBlur={this.finishEdit} 
     onKeyPress={this.checkEnter} 
     /> 
    ) 
    }; 

    renderDelete =() => { 
    return <button onClick={this.props.onDelete}>x</button>; 
    }; 

    renderItem =() => { 
    const onDelete = this.props.onDelete; 

    return (
     <div onClick={this.edit}> 
     <span>{this.props.text}</span> 
     {onDelete ? this.renderDelete() : null } 
     </div> 
    ); 
    }; 

    edit =() => { 
    this.setState({ 
     isEditing: true 
    }); 
    }; 

    checkEnter = (e) => { 
    if(e.key === 'Enter') { 
     this.finishEdit(e); 
    } 
    }; 

    finishEdit = (e) => { 
    const value = e.target.value; 

    if(this.props.onEdit) { 
     this.props.onEdit(value); 

     this.setState({ 
     isEditing: false 
     }); 
    } 
    }; 
} 

/components/Items.jsx

import React from 'react'; 
import Item from './Item.jsx'; 

export default ({items, onEdit, onDelete}) => { 
    return (
    <ul>{items.map(item => 
     <li key={item.id}> 
     <Item 
      text={item.text} 
      onEdit={onEdit.bind(null, item.id)} 
      onDelete={onDelete.bind(null, item.id)} 
     /> 
     </li> 
    )}</ul> 
); 
} 
// UPDATE: http://redux.js.org/docs/basics/UsageWithReact.html 
// Is this necessary? 
const mapStateToProps = (state) => { 
    return { 
    state 
    } 
} 

Items = connect(
    mapStateToPros 
)(Items) // `SyntaxError app/components/Items.jsx: "Items" is read-only` 

////////////////////////////////////// 
// Also tried it this way. 
////////////////////////////////////// 
Items = connect()(Items) 
export default Items // same error as above. 

schon versucht, diese auch

export default connect(
    state => ({ 
    items: store.items 
    }) 
)(Items) // `Uncaught TypeError: Cannot read property 'items' of undefined` 

UPDATE:

Nach vielen Versuche @hedgerh in Gitters wiesen darauf hin Es sollte stattdessen state.items sein. so war die Lösung

export default connect(
    state => ({ 
    items: state.items 
    }) 
)(Items) 

Kredite an @azium auch.

/components/App.jsx

export default class App extends React.Component { 
    render() { 
    return (
    <div> 
     <button onClick={this.addItem}>+</button> 
      <Items /> 
     </div> 
    ); 
    } 
} 

Was soll ich hier fehlt, um es richtig zu implementieren? Gerade jetzt bricht es, dass Uncaught TypeError: Cannot read property 'map' of undefined in Items.jsx sagend. Ich denke, es macht Sinn, da es nicht richtig angeschlossen zu sein scheint. Dies ist der erste Teil der App, in dem die zweite Möglichkeit es einem Benutzer ermöglicht, viele Listen zu erstellen, und diese Listen viele Elemente enthalten. Ich werde wahrscheinlich die Methoden aus Item.jsx extrahieren müssen, da die List.jsx ziemlich genau dasselbe tun wird. Danke

+0

Sie scheinen 'App.jsx' in Ihrem Beispiel zu fehlen .. Wie wird' Items' an ' '' übergeben? – azium

+0

Etwas muss mit Ihrem Geschäft verbunden werden. Sie haben also entweder vergessen, dieses Teil anzuzeigen, oder Sie müssen es irgendwo hinzufügen. – azium

+0

Ich denke das ist, was ich unsicher bin. Ich habe eine App.jsx, halt ich werde meine Frage aktualisieren. @azium – Diego

Antwort

2

Sie vermissen connect. So kommt das Zeug von Ihrem Geschäft zu Ihren Komponenten. Lesen Sie den Container Abschnitt von den docs http://redux.js.org/docs/basics/UsageWithReact.html

import React from 'react' 
import Item from './Item.jsx' 

import { connect } from 'react-redux' 

let Items = ({items, onEdit, onDelete}) => { 
    return (
    <ul>{items.map(item => 
     <li key={item.id}> 
     <Item 
      text={item.text} 
      onEdit={onEdit.bind(null, item.id)} 
      onDelete={onDelete.bind(null, item.id)} 
     /> 
     </li> 
     }) 
    </ul> 
) 
} 

export default connect(
    state => ({ 
    items: state.items 
    }) 
)(Items) 

Auch scheinen Sie onEdit und onDelete Funktionen von einem Elternteil weitergegeben erwartet zu werden, aber du bist nicht zu tun, dass so werden diese Funktionen nicht definiert werden.

+0

Es besagt, dass es den 'Speicher' nicht finden kann, den ich in meinem' index.jsx' angelegt habe. Soll ich es in einer anderen Datei erstellen? Sagen Sie 'stores/store.js' und importieren Sie das dann hier? @azium – Diego

+0

Sie importieren die falsche Datei in 'index.jsx'. Es sollte 'Import ShoppingList from '/ reducers' sein. Momentan importierst du den Reducer, ohne "combinateReducers" zu nennen. – azium

+0

Nach deinen vorgeschlagenen Änderungen erhalte ich "Uncaught TypeError: Kann nicht lesen" -Elemente 'undefined' in meinem 'Items.jsx' unter' store.items' – Diego