【问题标题】:Update State in function outside class component在类组件外的函数中更新状态
【发布时间】:2019-10-31 17:20:18
【问题描述】:

我有一个类组件,其中调用了一个函数。我有一个状态变量,想更新函数中的状态。由于它是不同的功能,我无法更新该值。如何获取所选项目的详细信息并更新状态?当我执行 setState 时,收到以下错误为 'TypeError: this.setState is not a function'

任何帮助表示赞赏 组件

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

【问题讨论】:

  • 那里有很多代码。通过将问题归结为基本要素,而不是发布整个实现,您可能会得到更多答案。

标签: javascript reactjs


【解决方案1】:

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

您需要做的是将一个函数作为 prop 传递给您的 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>
        )
    }
}

另外,我建议使用useCallback 钩子将事件处理函数封装在功能性DownshiftMultiple 组件中。像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]);

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2022-07-19
      • 2021-08-24
      • 2021-10-06
      • 1970-01-01
      • 2021-08-02
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      相关资源
      最近更新 更多