Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError this.props.addNode is not a function

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));
like image 956
Tyler Crawley Avatar asked Feb 14 '26 01:02

Tyler Crawley


1 Answers

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>
);
...
like image 114
Jemi Salo Avatar answered Feb 16 '26 14:02

Jemi Salo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!