Я пытаюсь настроить RactiveJS с помощью Redux для небольшого примера приложения - инициализировать панель управления (из AJAX), добавлять/удалять элементы (виджеты) из панели мониторинга (и сохранять сериализованные данные на сервере). Поскольку для React есть учебники почти исключительно, мне нужен совет. Я последовал за некоторые и получили структуру каталогов, как:RactiveJS + Действия отправки и гидраты Redux
views
app.html
dashboard.html
widget.html
js
actions
DashboardActions.js
components
Dashboard.js
Widget.js
constants
ActionTypes.js
reducers
dashboard.js
index.js
app.js
index.html
Этот пример работает, но есть несколько проблем, и я хотел бы, чтобы выяснить, как сделать его лучше. Например:
1) Как пройти (и я должен пройти?) Хранилище и действия до дерева активных компонентов? В настоящее время он использует bindActionCreators
в каждом компоненте, и я думаю, что это нехорошее решение.
2) Где положить начальную гидратацию состояния с сервера? В настоящее время он жестко закодирован в reducers/dashboard.js
, но я хотел бы использовать backend в качестве источника данных и конечной точки сохранения данных. Существует подход промежуточного уровня, но если это хорошая практика, то как применить это с помощью RactiveJs?
3) Должен ли я использовать один большой reducer
или по каждому компоненту один reducer
?
4) Возможно, основная концепция неверна и должна быть реорганизована?
просмотров/app.html
<Dashboard dashboard={{store.getState()}} store="{{store}}"></Dashboard>
просмотров/dashboard.html
{{#with dashboard}}
<pre>
====
<a on-click="@this.addWidget('Added by click')" href="#">Add New</a>
{{#dashboard}}
{{#each widgets}}
<Widget id="{{this.id}}" name="{{this.name}}" size="{{this.size}}" actions="{{actions}}" store="{{store}}"></Widget>
{{/each}}
{{/dashboard}}
====
</pre>
{{/with}}
просмотров/widget.html
<div>{{id}}-{{name}} (Size: {{size}})<a href="#" on-click="@this.deleteWidget(id)">X</a></div>
действия/DashboardActions.js
import * as types from '../constants/ActionTypes';
// Add widget to dashboard
export function addWidget(name) {
return {
type: types.ADD_WIDGET,
name
};
}
// Delete widget from dashboard
export function deleteWidget(id) {
return {
type: types.DELETE_WIDGET,
id
};
}
компоненты/Dashboard.js
import Ractive from 'ractive'
import * as DashboardActions from '../actions/DashboardActions';
import { dispatch, bindActionCreators } from 'redux'
import Widget from './Widget'
import template from '../../views/dashboard.html';
export default Ractive.extend({
isolated: true,
components: {
Widget
},
oninit() {
const store = this.get("store");
const actions = bindActionCreators(DashboardActions, store.dispatch);
this.set("actions", actions);
},
addWidget(name) {
this.get("actions").addWidget(name);
},
template: template
});
компоненты/Widget.js
import Ractive from 'ractive'
import * as DashboardActions from '../actions/DashboardActions';
import { dispatch, bindActionCreators } from 'redux'
import template from '../../views/widget.html';
export default Ractive.extend({
isolated: true,
template: template,
oninit() {
console.log(this.get("actions"));
const store = this.get("store");
const actions = bindActionCreators(DashboardActions, store.dispatch);
this.set("actions", actions);
},
deleteWidget(id) {
this.get("actions").deleteWidget(id);
},
})
константы/ActionTypes.js
// Add widget to dashboard
export const ADD_WIDGET = 'ADD_WIDGET';
// Delete widget from dashboard
export const DELETE_WIDGET = 'DELETE_WIDGET';
редукторы/dashboard.js
import * as types from '../constants/ActionTypes';
const initialState = {
widgets: [
{id: 1, name: "First widget"},
{id: 2, name: "Second widget"},
{id: 3, name: "Third widget"},
],
};
export default function dashboard(state = initialState, action) {
switch (action.type) {
case types.ADD_WIDGET:
const newId = state.widgets.length + 1;
const addedWidgets = [].concat(state.widgets, {
id: newId,
name: action.name
});
return {
widgets: addedWidgets
}
case types.DELETE_WIDGET:
const newWidgets = state.widgets.filter(function(obj) {
return obj.id != action.id
});
return {
widgets: newWidgets
}
default:
return state;
}
}
редукторы/index.js
export { default as dashboard } from './dashboard';
app.js
import Ractive from 'ractive';
import template from '../views/app.html';
import Dashboard from './components/Dashboard.js'
import { createStore, combineReducers, bindActionCreators } from 'redux'
import * as reducers from './reducers'
const reducer = combineReducers(reducers);
const store = createStore(reducer);
let App = new Ractive({
el: '#app',
template: template,
components: {
Dashboard
},
data: {
store
}
});
store.subscribe(() => App.update());
export default App;
Спасибо!
Спасибо! Можете ли вы дать мне несколько примеров кода, по крайней мере, для первого вопроса («Как передать (и должен ли я пройти?) Хранилище и действия до дерева активных компонентов? В настоящее время он использует bindActionCreators в каждом компоненте, и я думаю, что это нехорошее решение .')? – Orbitum
@Orbitum ответ обновлен :) – Joseph
Я принял ваш ответ, и это полезно, я реорганизовал код, как вы упомянули. Спасибо! – Orbitum