I'm extremely new to react/redux and very mediocre at Javascript, but I've been struggling with this for over a week now. Here's what I'm trying to do:
Clicking one of the navigation menu items on the left should dispatch an action to set the selected index in the store (at this point the entire store is just a number). When the index is updated it should automatically be reflected in the UI, at least by changing the css class of the selected item, but eventually it should toggle visibility for content components on the right.
Sidebar.js:
import React, { Component } from 'react';
import SidebarItem from './SidebarItem'
import ActionCreators from '../actions'
import { connect } from 'react-redux'
export default class Sidebar extends Component
{
handleClick(index)
{
//Dispatch action here maybe?
this.props.selectedSidebarItem(index);
console.log(this);
}
render()
{
var sidebarItemNames = ["Verify Original Contract", "Evaluate Transfer Terms", "Create Future Customer", "Check Credit", "Generate Agreement", "Finalize Transfer"];
return (
<div>
<div id="sidebar-title">
<div id="sc-logo">
LOGO
</div>
<div>Contract Transfer for:</div>
<div>XYZ</div>
<br />
</div>
<ul className="list-group" id="sidebar-list">
{sidebarItemNames.map(function(n, index)
{
return <SidebarItem key={index} index={index} selectedIndex={this.selectedSidebarItem} name={n} handleClick={this.handleClick(index).bind(this)} />;
})}
</ul>
</div>
)
}
}
function mapDispatchToProps(dispatch) {
return {
selectedSidebarItem: (index) => dispatch(ActionCreators.setSelectedSidebarItem(index))
}
}
const conn = connect(
null,
mapDispatchToProps
)(Sidebar)
SidebarItem.js:
import React, { Component } from 'react';
import ActionCreators from '../actions'
import { connect } from 'react-redux'
export class SidebarItem extends Component {
constructor(props) {
super(props);
}
setSelectedSidebarItem() {
this.props.handleClick(this.props.index);
this.props.selectedSidebarItem(this.props.index);
// const ul = document.getElementById('sidebar-list');
// const items = ul.getElementsByTagName('li');
// for (let i = 0; i < items.length; ++i) {
// items[i].classList.remove('sidebar-item-current');
// }
}
render() {
return (
<li className={"list-group-item sidebar-list-item sidebar-item-todo" + (this.props.index==this.props.selectedIndex? ' sidebar-item-current':'') } onClick={this.setSelectedSidebarItem.bind(this)}><i className="fa fa-circle fa-lg"></i> <span>{this.props.name}</span></li>
)
}
}
Store.js: import { createStore } from 'redux' import reducers from './Reducers'
const store = createStore(reducers)
export default store
Reducers.js
const initialState = {
selectedSidebarItem: window.initialPageState,
otherStuff: 5
};
const reducers = (state = initialState, action) => {
switch (action.type) {
case "SET_SELECTED_SIDEBAR_ITEM":
console.log("clicked sidebar index: " + action.index);
var result = Object.assign({}, state, {
selectedSidebarItem: action.index
})
console.log(result);
return result;
default:
return state
}
}
export default reducers
actions.js:
import constants from './constants'
let ActionCreators = {
setSelectedSidebarItem(index) {
var actionObject = {
type: constants.UPDATE_SELECTED_SIDEBAR_ITEM,
index
}
console.log("setting sidebar item", actionObject);
return actionObject
}
}
export default ActionCreators
Constants.js
const constants = {
UPDATE_SELECTED_SIDEBAR_ITEM: "UPDATE_SELECTED_SIDEBAR_ITEM",
ADD_ERROR: "ADD_ERROR",
CLEAR_ERROR: "CLEAR_ERROR"
};
export default constants;
I've tried a few variations of the above and have previously been able to dispatch actions, but am unsure the store is ever updated and nothing is reflected on the UI. Right now I'm getting this error when clicking sidebar items: "Cannot read property 'handleClick' of undefined"
Thanks for any help in advance.