TypeError this.props.addNode不是函数

时间:2018-12-28 17:21:45

标签: javascript reactjs redux react-redux

我在此组件中调用的任何动作似乎都给出相同的错误,而我可以在另一个组件中调用相同的动作,这没有问题。我已经检查了导入,连接/路由器,参数,操作,路由,我无法弄清楚这一点。特别是addNode动作。

这是组件:

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));

这是动作创建者:

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
            })

        );
}

供参考,这是我的其他组件,同样的操作可以正常工作。

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));

1 个答案:

答案 0 :(得分:1)

由于在纯props.addNode组件上调用Interests而收到错误。 props.addNode仅在要导出的高阶组件中定义。您错误地使用了普通的,未连接的组件,该组件上没有connectwithRouter的绒毛:

...
listItems = this.props.tree2.children.map((node) =>
  <div key = {node.name}>
    <Interests key = {node.name} tree2 = {node} />
  </div>
);
...

涂抹绒毛后一切都会好起来的

...
const InterestsWithFluff = connect(...)(withRouter(Interests))
listItems = this.props.tree2.children.map((node) =>
  <div key = {node.name}>
    <InterestsWithFluff key = {node.name} tree2 = {node} />
  </div>
);
...