Any action I call in this component seems to give same error, whereas I can call the same actions in another component and there is no problem. I have checked the imports, the connect/router, the parameters, the action, the route, I cant figure this one out. it is the addNode action in particular.
here is the component:
import React, { Component } from 'react'
import {connect} from 'react-redux';
import {withRouter} from "react-router-dom";
import PropTypes from 'prop-types';
import "./AddPersonStyles.css";
import TextFieldGroup from "../common/TextFieldGroup";
import {addNode,getNodes} from "../../actions/nodeActions";
import {getTree,test} from "../../actions/treeactions";
class Interests extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
parentName: ""
}
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
//this.props.test();
}
componentDidMount(){
}
onSubmit(e){
e.preventDefault();
const data = {
name: this.state.name
}
console.log(data.name, this.state.parentName );
this.props.addNode("Books", "Cultural");
}
onChange(e) {
this.setState({[e.target.name]: e.target.value});
}
render() {
const { displayChildren} = this.state;
let children;
let listItems;
if(!(this.props.tree2 === "" || undefined)){
console.log(this.props.tree2.children);
listItems = this.props.tree2.children.map((node) =>
<div key = {node.name}>
<Interests key = {node.name} tree2 = {node} />
</div>
);
console.log(listItems);
}
if(displayChildren){
children = (
<div className = "nodeContainer">
{listItems}
<form className ="newChild" onSubmit = {this.onSubmit}>
<div className = "row derp">
<input
className = "form-control squish form-control-lg"
placeholder="name"
name="name"
value = {this.state.name}
onChange = {this.onChange}
autoComplete = "off"
/>
<input type = "submit" value= "+" className = "btn btn-info butt"/>
</div>
</form>
</div>
)
}else{
children = (
<div></div>
)
}
let buttonName = "test";
if(!(this.props.tree2 === "")){
console.log(this.props.tree2.name);
buttonName = this.props.tree2.name;
this.state.parentName = buttonName;
}
console.log("hello")
return (
<div>
<div className = "d-flex nodeContainer flex-row ml-2 bd-highlight mb-2">
<button type = "button" className = "btn btn-info ml-2" onClick ={() => {
this.setState(prevState => ({
displayChildren: !prevState.displayChildren
}))
}}>
{buttonName}
</button>
</div>
<div className = "col nodeStack">
{children}
</div>
</div>
)
}
}
Interests.propTypes = {
//getNodes: PropTypes.func.isRequired,
//node: PropTypes.object.isRequired
//getTree: PropTypes.func.isRequired,
//tree: PropTypes.object.isRequired,
//test: PropTypes.func.isRequired
//addNode: PropTypes.func
//errors: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
//node: state.node
//tree: state.tree
//errors: state.errors
})
export default connect(mapStateToProps, {addNode, getNodes, getTree, test})(withRouter(Interests));
And here is the action creator:
import { GET_ERRORS, GET_NODE} from './types';
import axios from 'axios';
export const addNode = (name, parent) => dispatch => {
axios
.post('/api/nodes/', {name, parent} )
.then(res => console.log(res))
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
}
export const getNodes = () => dispatch => {
axios
.get("/api/nodes/")
.then(res =>
dispatch({
type: GET_NODE,
payload: res.data
}),
)
.catch(err =>
dispatch({
type: GET_NODE,
payload: null
})
);
}
and for reference, here is my other component where same action will work fine.
import React, { Component } from 'react'
import {connect} from 'react-redux';
import {withRouter} from "react-router-dom";
import PropTypes from 'prop-types';
import TextFieldGroup from "../common/TextFieldGroup";
import TextAreaFieldGroup from "../common/TextAreaFieldGroup";
import SelectListGroup from "../common/SelectListGroup";
import {createProfile} from "../../actions/profileActions";
import Interests from "./Interests";
import{getTree,test} from "../../actions/treeactions";
import {addNode} from "../../actions/nodeActions";
import "./AddPersonStyles.css";
class AddPerson extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
sex: "",
age: "",
city: "",
state: "",
interests: "",
bio: "",
errors: {}
}
this.props.test();
//this.props.addNode("Books", "Conceptual");
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onSelectChange = this.onSelectChange.bind(this);
}
componentDidMount(){
}
componentWillReceiveProps(nextProps){
if(nextProps.errors){
this.setState({errors: nextProps.errors});
}
}
onSubmit(e){
e.preventDefault();
const profileData = {
name: this.state.name,
sex: this.state.sex,
age: this.state.age,
city: this.state.city,
state: this.state.state,
interests: this.state.interests,
bio: this.state.bio
}
//console.log(profileData);
this.props.createProfile(profileData, this.props.history);
}
onChange(e) {
this.setState({[e.target.name]: e.target.value});
}
onSelectChange(e) {
this.setState({status: e.target.value});
console.log(this.status);
console.log("derp");
}
render() {
const {errors} = this.state;
const {tree} = this.props;
console.log(tree);
console.log("here2");
//select options for status
const options = [
{
label: 'male',
value: "male"
},
{label: 'female', value: "female"}
];
return (
<div className = "add-person">
<div className = "container">
<div className = "row">
<div className = "col-md-8 m-auto">
<h1 className = "display-4 text-center">Add Person</h1>
<p className = "lead text-center">
enter info
</p>
<small className = "d-block pb-3">* = required fields</small>
<form onSubmit = {this.onSubmit}>
<TextFieldGroup
placeholder = "name"
name = "name"
value = {this.state.name}
onChange = {this.onChange}
error = {errors.name}
info = "name"
autoComplete = "off"
/>
<SelectListGroup
placeholder = "sex"
name = "sex"
value = {this.state.sex}
onChange = {this.onChange}
options = {options}
error = {errors.sex}
info = "sex"
/>
<TextFieldGroup
placeholder = "age"
name = "age"
value = {this.state.age}
onChange = {this.onChange}
error = {errors.age}
info = "age"
/>
<TextFieldGroup
placeholder = "city"
name = "city"
value = {this.state.city}
onChange = {this.onChange}
error = {errors.city}
info = "city"
/>
<TextFieldGroup
placeholder = "state"
name = "state"
value = {this.state.state}
onChange = {this.onChange}
error = {errors.state}
info = "state"
/>
<TextFieldGroup
placeholder = "interests"
name = "interests"
value = {this.state.interests}
onChange = {this.onChange}
error = {errors.interests}
info = "interests"
/>
<TextAreaFieldGroup
placeholder = "bio"
name = "bio"
value = {this.state.bio}
onChange = {this.onChange}
error = {errors.bio}
info = "bio"
/>
<input type = "submit" value= "Submit" className = "btn btn-info btn-block mt-4"/>
</form>
</div>
</div>
</div>
<br />
<div className = "interests">
<div className = "row">
<div className = "col">
<br />
<h1 className = "display-4 text-center">Interests</h1>
<Interests tree2 = {tree.tree} />
{console.log(tree.tree)}
<div className = "container">
</div>
</div>
</div>
</div>
</div>
)
}
}
AddPerson.propTypes = {
profile: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
test: PropTypes.func.isRequired,
tree: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
profile: state.profile,
errors: state.errors,
tree: state.tree
});
export default connect(mapStateToProps, {createProfile, addNode, test})(withRouter(AddPerson));
You're getting the error because you're calling props.addNode on a plain Interests component. props.addNode is only defined in the higher order component that is being exported. You're mistakenly using the plain and unconnected component, which doesn't have the connect and withRouter fluff on it:
...
listItems = this.props.tree2.children.map((node) =>
<div key = {node.name}>
<Interests key = {node.name} tree2 = {node} />
</div>
);
...
All will be well when you apply the fluff:
...
const InterestsWithFluff = connect(...)(withRouter(Interests))
listItems = this.props.tree2.children.map((node) =>
<div key = {node.name}>
<InterestsWithFluff key = {node.name} tree2 = {node} />
</div>
);
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With