React setState не будет обновлять состояние при вызове вне компонента класса

#javascript #arrays #reactjs #react-state

Вопрос:

Поэтому для школьного проекта мне нужно создать веб-сайт с использованием javascript и реагировать. У меня есть два объекта, эксперимент с компонентами класса и надстройщики компонентов класса. Классу эксперимента потребуется несколько параметров, прежде чем он сможет опубликовать их в нашем API и запустить эксперимент. Одной из таких вещей является список, содержащий несколько идентификаторов пользователя. Этот список можно получить с помощью других пользователей классов. Оба класса хранят список под названием m_DataUsers в своем состоянии, представляющем список идентификаторов пользователей. В то время как все работает идеально при добавлении пользователей, проблема возникает при изменении состояния эксперимента в классе AddUser. Я следовал учебнику, используя этот сайт: https://www.codeproject.com/Tips/1215984/Update-State-of-a-Component-from-Another-in-React

В принципе, мне нужно определить функцию вне класса эксперимента, которая обновляет состояние с помощью setState (), я использовал updateDataUsers(источники данных), а затем привязал ее к классу эксперимента. Поправьте меня, если я ошибаюсь, но я не думаю, что имеет значение, где я привязываю функцию, поэтому я привязываю ее сразу после определения состояния в конструкторе эксперимента. Я экспортирую эту функцию updateDataUsers, поэтому вызываю ее из класса AddUser. При вызове функции я вижу, что класс AddUsers успешно отправил свой массив идентификаторов пользователя (я вошел в консоль). Но после вызова setState () состояние остается неизменным.

Я поискал в Интернете и обнаружил, что после вызова setState () состояние не обязательно будет обновляться непосредственно после вызова setState(). На самом деле это не проблема, но при отправке в API массив m_DataUsers по-прежнему пуст, и я также получаю пустой список в своем API. Поэтому я думаю, что по какой-то причине функция setState() не обновляет состояние эксперимента.

Вот моя функция 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", {userName: store.getState().userName, 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, color: 'white', top: 15, width: '10vw'}}>
                            delete
                        </Button>
                    </ListItem>
                    <ListItem>
                        <AddUsers experimentName={this.state.m_Name}/>
                    </ListItem>
                </List>
            </Box>
        </RightBar>
    )
}
}
 

And at last, here is my AddUsers class

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

    }
}

getDataUsers(){
    axios.post("/api/workspace/getdatasetusers", {userName: store.getState().userName, 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, color: 'white', top: 15, 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>
    )
}
}
 

Thanks in advance