Attualmente sto cercando di imparare Redux e penso di doverlo implementare in modo errato in quanto solo l'ultimo componente da rendere sulla pagina funziona effettivamente. Sospetto che lo stato venga sovrascritto ogni volta.Lo stato sembra essere sovrascritto invece di unire
Ho seguito il tutorial this che utilizza solo un esempio di recupero dei dati, quindi probabilmente ho appena frainteso come scrivere nello stato.
Ecco il mio riduttore. Qualche idea in cui ho sbagliato? Anche questo sembra molto prolisso, c'è un modo DRYer di scrivere questo?
import Immutable from 'seamless-immutable';
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
// Import actions
import {
REQUEST_CONFIG,
GET_CONFIG,
REQUEST_PAGES,
GET_PAGES,
REQUEST_SOCIAL_LINKS,
GET_SOCIAL_LINKS,
REQUEST_NAV,
GET_NAV
} from './actions';
const configInitialState = Immutable({
items: [],
isFetching: false
})
const pagesInitialState = Immutable({
items: [],
isFetching: false
})
const socialLinksInitialState = Immutable({
items: [],
isFetching: false
})
const navInitialState = Immutable({
items: [],
isFetching: false
})
export function config(state = configInitialState, action) {
switch (action.type) {
case GET_CONFIG :
return Immutable(state).merge({
items: action.payload.config[0],
isFetching: false
})
case REQUEST_CONFIG :
return Immutable(state).merge({
isFetching: true
})
default:
return state;
}
}
export function pages(state = pagesInitialState, action) {
switch (action.type) {
case GET_PAGES :
return Immutable(state).merge({
items: action.payload.pages,
isFetching: false
})
case REQUEST_PAGES :
return Immutable(state).merge({
isFetching: true
})
default:
return state;
}
}
export function socialLinks(state = socialLinksInitialState, action) {
switch (action.type) {
case GET_SOCIAL_LINKS :
return Immutable(state).merge({
items: action.payload.socialLinks,
isFetching: false
})
case REQUEST_SOCIAL_LINKS :
return Immutable(state).merge({
isFetching: true
})
default:
return state;
}
}
export function nav(state = navInitialState, action) {
switch (action.type) {
case GET_NAV :
return Immutable(state).merge({
items: action.payload.nav,
isFetching: false
})
case REQUEST_NAV :
return Immutable(state).merge({
isFetching: true
})
default:
return state;
}
}
const rootReducer = combineReducers({
config,
pages,
socialLinks,
nav,
routing: routerReducer
});
export default rootReducer;
Solo nel caso è richiesto, ecco un esempio di uno dei miei componenti così:
import React from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { navLoad } from '../../../scripts/actions';
export default class HeaderNav extends React.Component {
componentWillMount() {
const { dispatch } = this.props;
dispatch(navLoad());
}
render() {
const { nav } = this.props;
const navitems = nav && nav.items ? nav.items.asMutable().map((item) => {
if(item.inNav === 'header' || item.inNav === 'both') {
return <li key={item._id}><Link to={item.slug}>{item.name}</Link></li>
}
}) : null;
if(nav.isFetching) {
return(
<section class="loader">
<span>Content is loading...</span>
</section>
)
} else {
return(
<nav class="c-primary-nav">
<span class="c-primary-nav_toggle">Menu</span>
<ul>
{ navitems }
</ul>
</nav>
)
}
}
}
function select(state) {
const { nav } = state;
return {
nav
};
}
export default connect(select)(HeaderNav);
e qui è dove i componenti si chiamano:
import React from 'react';
import HeaderNav from './Header/nav.jsx';
import SocialLinks from './Header/socialLinks.jsx';
export default class Header extends React.Component {
render() {
return(
<header class="c-global-header" role="banner">
<HeaderNav />
<SocialLinks />
</header>
)
}
}
Aggiornamento: Sto ancora sperando in una risposta a questa domanda perché mi sta ancora bloccando, ho modificato il codice un po 'ora ma senza successo. Puoi vedere il mio full codebase qui: https://github.com/alexward1981/portfolio-react (Tutte le cose rilevanti sono nella cartella 'src')
Puoi spiegare il problema in modo più dettagliato? Cosa intendi quando dici "solo l'ultimo componente da renderizzare funziona"? Cosa sta succedendo/non funziona in modo specifico? – azium
Quindi la mia pagina esegue il rendering di due componenti, e Se Nav è l'ultimo componente visualizzato sulla pagina, i dati vengono trascinati nello stato e il componente viene visualizzato, ma i collegamenti social vengono ignorati, è vero anche il contrario . Non ricevo messaggi di errore, il primo componente è semplicemente ignorato. (Ho aggiunto il componente che chiama questi componenti alla domanda) –
@AlexWard un problema che vedo è che stai esportando due membri nel tuo file come esportazioni predefinite: 'Esporta la classe predefinita HeaderNav estende React.Component' e' esportazione predefinita connect (seleziona) (HeaderNav); '. Solo uno dovrebbe essere esportato come predefinito (nel tuo caso, di sicuro è il secondo). In TypeScript, si otterrebbe un errore, ma probabilmente usando Babel, esso semplicemente esporterà come predefinito le prime esportazioni predefinite trovate nel file, e probabilmente questo è il motivo per cui le cose non funzionano per te. – Buzinas