微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在类组件之外调用时,React setState 不会更新状态

如何解决在类组件之外调用时,React setState 不会更新状态

所以对于学校项目,我需要使用 javascript 和 React 设计一个网站。我有两个对象,一个类组件实验和一个类组件 AddUsers。实验类需要一些参数才能发布到我们的 API 并运行实验。其中之一是包含一些用户 ID 的列表。可以使用其他类 AddUsers 获得此列表。 这两个类都在它们的状态中存储一个名为 m_DataUsers 的列表,表示用户 ID 的列表。 虽然添加用户时一切正常,但在 AddUser 类中更改 Experiment 的状态时会出现问题。我使用此网站遵循了教程:https://www.codeproject.com/Tips/1215984/Update-State-of-a-Component-from-Another-in-React

基本上,我需要在 Experiment 类之外定义一个函数,它使用 setState() 更新状态,我使用了 updateDataUsers(dataUsers),然后将其绑定到实验类。如果我错了,请纠正我,但我认为绑定函数的位置无关紧要,所以我在实验的构造函数中定义状态后才绑定它。我导出这个 updateDataUsers 函数,所以我从 AddUser 类调用它。调用函数时,我可以看到 AddUsers 类成功提交了他的用户 ID 数组(我登录了控制台)。但是调用setState()后,状态不变。

我上网查了一下,发现调用setState()后,状态不一定会在调用setState()后直接更新。这不是一个真正的问题,但是当发布到 API 时,m_DataUsers 数组仍然是空的,而且我的 API 中也收到了一个空列表。所以我认为由于某种原因,setState() 函数没有更新 Experiment 的状态。

这是我的 updateDataUsers 函数

export function updateDataUsers(dataUsers){
    this.setState({
            m_DataUsers: dataUsers,});
    console.log(this)
}

这是我的实验课

export default class Experiment extends React.Component{
constructor(experimentName,datasetName,props) {
    super(props);
    this.state = {
        m_Name: experimentName,m_DatasetName: datasetName,m_Loading: false,m_DataUsers: [],}



    updateDataUsers = updateDataUsers.bind(this);


}

getName(){
    return this.state.m_Name;
}

runExperiment(){
    console.log("RUNNING EXPERIMENT: ",this.state.m_DataUsers);
    axios.post("/api/workspace/run",{userName: store.getState().userName,experimentName: this.state.m_Name,ids: this.state.m_DataUsers,nrOfRecommendations: 5})
        .then(response =>  {
            if (response.data.isSuccessful === "True"){
                 console.log("EXPERIMENT SUCCESSFUL",response.data);
            }
            else{
                console.log(response.data.info)
            }
        })
        .catch(error => console.log(error))
}

delete(){
    axios.post("/api/workspace/deleteexperiment",experimentName: this.state.m_Name})
        .then(response => {
            if (response.data.isSuccessful === "True"){
                console.log("deleted");
                updateWorkspace();
            }
            else{
                console.log(response.data.info)
            }
        })
}


render() {
    return (
        <RightBar>
            <Box display="flex" alignContent="center">
                <List style={{color: 'black'}}>
                    <ListItem>
                        <Typography variant="h6">
                            {this.state.m_Name}
                        </Typography>
                    </ListItem>
                    <Divider/>
                    <ListItem>
                        <Button variant="contained" onClick={() => this.runExperiment() }
                                style={{backgroundColor: colorScheme.primaryColor,color: 'white',top: 15,width: '10vw'}}>
                            run
                        </Button>
                    </ListItem>
                    <ListItem>
                        <Button variant="contained" onClick={() => this.delete() }
                                style={{backgroundColor: colorScheme.primaryColor,width: '10vw'}}>
                            delete
                        </Button>
                    </ListItem>
                    <ListItem>
                        <AddUsers experimentName={this.state.m_Name}/>
                    </ListItem>
                </List>
            </Box>
        </RightBar>
    )
}
}

最后,这是我的 AddUsers 类

export default class AddUsers extends React.Component{
constructor(props) {
    super(props);
    this.state = {
        m_ExperimentName: props.experimentName,m_SelectedDataUsers: [],m_GotDataUsers: false,m_IsOpen: false,}
}

getDataUsers(){
    axios.post("/api/workspace/getdatasetusers",experimentName: this.state.m_ExperimentName})
        .then(response => {
            if (response.data.isSuccessful === "True"){
                let tempList = []
                for (let i = 0; i < response.data.models[0].dataUsers.length; i++){
                    tempList.push({index: i,dataUserID: response.data.models[0].dataUsers[i].dataUserID.toString()})

                }
                this.setState({m_DataUsers: tempList,m_GotDataUsers: true})
            }
            else{
                console.log(response.data.info);
            }})

        .catch(err => console.log(err))
}

dialogSwitch(){
    if (this.state.m_IsOpen === true){
        this.setState({m_IsOpen: false});
    }
    else{
        this.setState({m_IsOpen: true});
    }
}

pickUsers(){
    const handleChange = (event) => {
        if (event.target.checked === true){
            let id = parseInt(event.target.name)
            let tempList = this.state.m_SelectedDataUsers;
            tempList.push(id);
            this.setState({m_SelectedDataUsers: tempList});
        }
        else{
            let id = parseInt(event.target.name);
            let tempList = this.state.m_SelectedDataUsers;
            let index = tempList.indexOf(id);
            tempList.splice(index,1);
            this.setState({m_SelectedDataUsers: tempList});
        }

    }
    return (
        <div className={{display: 'flex'}}>
            <FormControl component="fieldset">
                <Formlabel component="legend">
                    pick users
                </Formlabel>
                <FormGroup>
                    {
                        this.state.m_DataUsers.map(user =>{
                            return (
                                <FormControlLabel
                                    control={<CheckBox onChange={handleChange} name={user.dataUserID}/>}
                                    label={user.dataUserID}
                                />
                            )
                        })
                    }
                </FormGroup>
            </FormControl>
        </div>
    )
}

isIDPicked(id,selected){
    var found = false;
    for (let j = 0; j < selected.length; j++) {
        if (selected[j] === id) {
            found = true;
            break;
        }
    }
    if (found === false){
        return false;
    }
    else {
        return true;
    }
}

pickRandomUsers(){
    var randomNr = Math.floor(Math.random() * (this.state.m_DataUsers.length)) + 1;
    let selected = []
    for (let i = 0; i < randomNr; i++){
        var randomIndex = Math.floor(Math.random() * (this.state.m_DataUsers.length));
        var id = this.state.m_DataUsers[randomIndex].dataUserID;
        while (this.isIDPicked(id,selected) === true){
            randomIndex = Math.floor(Math.random() * (this.state.m_DataUsers.length));
            id = this.state.m_DataUsers[randomIndex].dataUserID;
        }
        selected.push(id);
    }
    this.setState({m_SelectedDataUsers: selected});
}

render() {
    if (this.state.m_GotDataUsers === false){
        this.getDataUsers();
    }
    return (
        <div>
            <Button
            variant="contained"
            style={{backgroundColor: colorScheme.primaryColor,width: '10vw'}}
            onClick={() => this.dialogSwitch()}
            >
                add users
            </Button>
            <Dialog open={this.state.m_IsOpen}>
                <DialogContent>
                    <Typography variant="h6">
                        Add users to experiment
                    </Typography>
                </DialogContent>
                <DialogContent>
                    <Button onClick={() => this.pickRandomUsers()}>
                        random
                    </Button>
                </DialogContent>
                <DialogContent>
                    {
                        this.pickUsers()
                    }
                </DialogContent>
                <DialogContent>
                    <Button onClick={() => this.dialogSwitch()}>
                        cancel
                    </Button>
                    <Button onClick={() => {
                        this.dialogSwitch();
                        updateDataUsers(this.state.m_SelectedDataUsers);
                    }}>
                        ok
                    </Button>
                </DialogContent>
            </Dialog>
        </div>
    )
}
}

提前致谢

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。