简体   繁体   English

子组件中的 useEffect 触发父 state 更改但具有旧父 state

[英]useEffect in child component triggers on parent state change but has old parent state

I have a parent component (IssueWindow) that passes it's state (issue) to a child component (IssueSidebar).我有一个父组件(IssueWindow),它将 state(问题)传递给子组件(IssueSidebar)。 When I make a state change in the child, I want to update the parent state by calling a parent function.当我在孩子中进行 state 更改时,我想通过调用父 function 来更新父 state。 I then have a useEffect setup in the child to detect this parent state change and then update the dropdown accordingly.然后我在孩子中有一个 useEffect 设置来检测这个父 state 更改,然后相应地更新下拉列表。

I am able to successfully make a change in the child and have it change the parent state.我能够成功地改变孩子并让它改变父母 state。 I can even trigger the useEffect in the child when the parent's state changes HOWEVER the state that the child has in this useEffect is actually the previous value instead of the most current value from the parent.我什至可以在父母的 state 发生变化时触发孩子的 useEffect 但是孩子在这个 useEffect 中的 state 实际上是以前的值而不是来自父母的最新值。

Any idea why this is happening?知道为什么会这样吗?

<!-- language: react -->
export default function IssueWindow() {
    //Load initial issue state
    useEffect(() => {
        return () => {
            axios.get(`${endpoints.issues}/${issueId}`)
                .then(response => {
                    setIssue(response.data);
                })
                .catch(error => console.error(`Error: ${error}`))
        };
    }, []);
    //Fires when issue changes in child components
    const updateIssue = (updateIssue) => {
        axios.post(`${endpoints.issues}`,updateIssue)
            .then(response => {
                setIssue(response.data);
            })
            .catch(error => console.error(`Error: ${error}`))
    }
    return (
        <Container className={"issue"} sx={{display:"flex", direction:"row"}}>
            <Grid container direction="row">
                <Grid container item xs={8} direction={"column"}>
                    {issue && <IssueDetails issue={issue} updateIssue={updateIssue}/>}
                    {issue && <IssueComments issue={issue} updateIssue={updateIssue}/>}
                </Grid>
                <Grid container item xs={4} direction={"column"}>
                    {issue && <IssueSidebar issue={issue} updateIssue={updateIssue}/>}
                </Grid>
            </Grid>
        </Container>
    )
}

export default function IssueSidebar(props) {
    //Store input value lists
    const [inputListValues, setInputListValues] = useState({});
    //Dropdown value states
    const [priority.InputValue, setStateInputValue] = useState(1);
    
    //Initial dropdown values
    useEffect(() => {
        return () => {
            //PRIORITY
            axios.get(`${endpoints.issues}/${props.issue.issueId}/state`)
                .then(response => {
                    setInputListValues(prevState => {
                        return {
                            ...prevState,
                            priority : response.data
                        }
                    })
                    setPriorityInputValue(response.data.indexOf(props.issue.priority))
                })
                .catch(error => console.error(`Error: ${error}`))
        };
    }, []);

    useEffect(() => {
        return () => {
            if (inputListValues.state && inputListValues.priority){
                //props.issue has old value here!
                setStateInputValue(inputListValues.state.indexOf(props.issue.state))
            }
        };
    }, [props.issue]);

    //Select dropdowns
    const handleDropdownChange = (e) =>{
        props.updateIssue({
            ...props.issue,
            [e.target.name] : inputListValues[e.target.name][e.target.value]
        });
    }
    
    return (
    <Grid className={"issue-sidebar"} container direction={"column"}>
        {/*PRIORITY*/}
        <Grid container direction={"row"} className={"issue-sidebar__row"}>
            <Grid><Typography className={"label"}>Priority:</Typography></Grid>
            { inputListValues.priority && (<Select name={"priority"} defaultValue={1} value={priorityInputValue} onChange={handleDropdownChange}>
                {inputListValues.priority.map((priority, index) => <MenuItem value={index} key={index}>{priority}</MenuItem>)}
            </Select>)}
        </Grid>
    </Grid>
    )
}

Maybe you should move codes from the useEffect's cleanup function:也许您应该从 useEffect 的清理 function 中移动代码:

    useEffect(() => {
        // add here
        if (inputListValues.state && inputListValues.priority){
setStateInputValue(inputListValues.state.indexOf(props.issue.state))
        }

        return () => {
            // remove from here
        };
    }, [props.issue]);

from react docs来自反应文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM