类组件外部函数的更新状态

时间:2019-06-18 06:16:46

标签: javascript reactjs

在调用函数的过程中,我有一个类组件。我有一个状态变量,想更新功能中的状态。由于功能不同,因此无法更新该值。如何获得所选项目的详细信息并更新状态?当我执行setState时,收到以下错误,提示为“ TypeError:this.setState不是函数”

任何帮助表示赞赏 组件

import React, { Component } from 'react'
import PropTypes from "prop-types";
import statedist from "./StateDistrict.json";

const suggestions = statedist.states;


function DownshiftMultiple(props) {
    const { classes } = props;
    const [inputValue, setInputValue] = React.useState("");
    const [selectedItem, setSelectedItem] = React.useState([]);

    function handleKeyDown(event) {
        if (
            selectedItem.length &&
            !inputValue.length &&
            event.key === "Backspace"
        ) {
            setSelectedItem(selectedItem.slice(0, selectedItem.length - 1));
        }
    }

    function handleInputChange(event) {
        setInputValue(event.target.value);
    }

    function handleChange(item) {
        let newSelectedItem = [...selectedItem];
        if (newSelectedItem.indexOf(item) === -1) {
            newSelectedItem = [...newSelectedItem, item];
        }
        setInputValue("");
        setSelectedItem(newSelectedItem);
         this.setState({ SelectedState: newSelectedItem }); // here i want to update selected items

    }

    const handleDelete = item => () => {
        const newSelectedItem = [...selectedItem];
        newSelectedItem.splice(newSelectedItem.indexOf(item), 1);
        setSelectedItem(newSelectedItem);
    };

    return (
        <Downshift
            id="downshift-multiple"
            inputValue={inputValue}
            onChange={handleChange}
            selectedItem={selectedItem}
        >
            {({
                getInputProps,
                getItemProps,
                getLabelProps,
                isOpen,
                inputValue: inputValue2,
                selectedItem: selectedItem2,
                highlightedIndex
            }) => {
                const { onBlur, onChange, onFocus, ...inputProps } = getInputProps({
                    onKeyDown: handleKeyDown,
                    // placeholder: "Select multiple State"
                });

                return (
                    <div className={classes.container}>
                        {renderInput({
                            fullWidth: true,
                            classes,
                            // label: "States",
                            InputLabelProps: getLabelProps(),
                            InputProps: {
                                startAdornment: selectedItem.map(item => (
                                    <Chip
                                        key={item}
                                        tabIndex={-1}
                                        label={item}
                                        className={classes.chip}
                                        onDelete={handleDelete(item)}
                                    />
                                )),
                                onBlur,
                                onChange: event => {
                                    handleInputChange(event);
                                    onChange(event);
                                },
                                onFocus
                            },
                            inputProps
                        })}

                        {isOpen ? (
                            <Paper className={classes.paper} square>
                                {getSuggestions(inputValue2).map((suggestion, index) =>
                                    renderSuggestion({
                                        suggestion,
                                        index,
                                        itemProps: getItemProps({ item: suggestion.state }),
                                        highlightedIndex,
                                        selectedItem: selectedItem2
                                    })
                                )}
                            </Paper>
                        ) : null}
                    </div>
                );
            }}
        </Downshift>
    );
}

class autoCompleteState extends Component {
    constructor(props) {
        super(props);
        this.state = {
            SelectedState:'',
        }
       // this.showProfile = this.showProfile.bind(this)
    }

    render() {
        const { classes, } = this.props;
        return (
            <div>
                <DownshiftMultiple classes={classes} />
            </div>
        )
    }
}
export default withStyles(Styles)(autoCompleteState);

2 个答案:

答案 0 :(得分:1)

您不能也不应该直接访问其他组件的上下文(this)以更新其状态,尤其是不能使用功能组件。

您需要做的是将一个函数作为道具传递给DownshiftMultiple组件,该组件本身会获取要用来更新状态的值。

function DownshiftMultiple(props) {
    /* ... */
    function handleChange(item) {
        let newSelectedItem = [...selectedItem];
        if (newSelectedItem.indexOf(item) === -1) {
            newSelectedItem = [...newSelectedItem, item];
        }
        setInputValue("");
        setSelectedItem(newSelectedItem);
        this.props.onChange(newSelectedItem); // Use the new function prop
    }

    /* ... */
}

class autoCompleteState extends Component {
    /* ... */

    onDMChange = (newSelectedItem) => this.setState({ SelectedState: newSelectedItem });

    render() {
        const { classes, } = this.props;
        return (
            <div>
                <DownshiftMultiple classes={classes} onChange={this.onChange} />
            </div>
        )
    }
}

我也建议在旁注中使用DownshiftMultiple钩子将事件处理函数封装在功能性useCallback组件中。像const newSelectedItem = [...selectedItem];这样的东西将始终使用状态初始化时没有钩子的值。

// For example your handle delete
const handleDelete = React.useCallback(item => () => {
    const newSelectedItem = [...selectedItem];
    newSelectedItem.splice(newSelectedItem.indexOf(item), 1);
    setSelectedItem(newSelectedItem);
}, [selectedItem]);

答案 1 :(得分:0)

您将处理程序传递给子组件,该子组件将使用要更新的值进行调用,并且更新操作在父组件中发生

import React, { Component } from 'react'
import PropTypes from "prop-types";
import statedist from "./StateDistrict.json";

const suggestions = statedist.states;


function DownshiftMultiple(props) {
    const { classes } = props;
    const [inputValue, setInputValue] = React.useState("");
    const [selectedItem, setSelectedItem] = React.useState([]);

    function handleKeyDown(event) {
        if (
            selectedItem.length &&
            !inputValue.length &&
            event.key === "Backspace"
        ) {
            setSelectedItem(selectedItem.slice(0, selectedItem.length - 1));
        }
    }

    function handleInputChange(event) {
        setInputValue(event.target.value);
    }

    function handleChange(item) {
        let newSelectedItem = [...selectedItem];
        if (newSelectedItem.indexOf(item) === -1) {
            newSelectedItem = [...newSelectedItem, item];
        }
        setInputValue("");
        setSelectedItem(newSelectedItem);
        props.setSelectedState(newSelectedItem);

    }

    const handleDelete = item => () => {
        const newSelectedItem = [...selectedItem];
        newSelectedItem.splice(newSelectedItem.indexOf(item), 1);
        setSelectedItem(newSelectedItem);
    };

    return (
        <Downshift
            id="downshift-multiple"
            inputValue={inputValue}
            onChange={handleChange}
            selectedItem={selectedItem}
        >
            {({
                getInputProps,
                getItemProps,
                getLabelProps,
                isOpen,
                inputValue: inputValue2,
                selectedItem: selectedItem2,
                highlightedIndex
            }) => {
                const { onBlur, onChange, onFocus, ...inputProps } = getInputProps({
                    onKeyDown: handleKeyDown,
                    // placeholder: "Select multiple State"
                });

                return (
                    <div className={classes.container}>
                        {renderInput({
                            fullWidth: true,
                            classes,
                            // label: "States",
                            InputLabelProps: getLabelProps(),
                            InputProps: {
                                startAdornment: selectedItem.map(item => (
                                    <Chip
                                        key={item}
                                        tabIndex={-1}
                                        label={item}
                                        className={classes.chip}
                                        onDelete={handleDelete(item)}
                                    />
                                )),
                                onBlur,
                                onChange: event => {
                                    handleInputChange(event);
                                    onChange(event);
                                },
                                onFocus
                            },
                            inputProps
                        })}

                        {isOpen ? (
                            <Paper className={classes.paper} square>
                                {getSuggestions(inputValue2).map((suggestion, index) =>
                                    renderSuggestion({
                                        suggestion,
                                        index,
                                        itemProps: getItemProps({ item: suggestion.state }),
                                        highlightedIndex,
                                        selectedItem: selectedItem2
                                    })
                                )}
                            </Paper>
                        ) : null}
                    </div>
                );
            }}
        </Downshift>
    );
}

class autoCompleteState extends Component {
    constructor(props) {
        super(props);
        this.state = {
            SelectedState:'',
        }
       // this.showProfile = this.showProfile.bind(this)
    }
    setSelectedState = (newState) => {
         this.setState({ SelectedState: newState });
    }
    render() {
        const { classes, } = this.props;
        return (
            <div>
                <DownshiftMultiple classes={classes} setSelectedState={this.setSelectedState}/>
            </div>
        )
    }
}
export default withStyles(Styles)(autoCompleteState);