Thbwun
Thbwun

Reputation: 343

useEffect is not triggered on rerender

I have a dashboard component in which I have two-component used to select the data I need to show. The first select indicates the client. The second select indicates the project. The options of the second select depend on the client that is selected.

I change the state in my dashboard when I select the client and I pass the id as a props to the second select. This works well and, after setting const selectedClient = props.selectedClient; in my second select if I make a console.log(selectedClient) I see that it changes.

However, the useEffect is not triggered when I select another client.

dashboard component

class Dashboard extends Component {
    constructor(props) {
        super(props);
    
        this.state = {
            selectedClient: JSON.parse(localStorage.getItem('appState')).user.id,
            selectedProject: 0
        };
    
        this.handleSelectChange = this.handleSelectChange.bind(this);
    }

    handleSelectChange(event) {
        this.setState({selectedClient: event.target.value});
    }

    handleProjectChoice(event) {
        this.setState({selectedProject: event.target.value});
    }

    render() {
        return (
            <div className={classes.Dashboard}>
                <div className="container-fluid">
                    <div className="row">
                        <div className={`col-md-8 offset-md-2 col-xl-4 offset-xl-4 ${classes.clientChoice}`}>
                            <ClientChoice selectedClient={this.state.selectedClient} changed={this.handleSelectChange} />
                        </div>
                    </div>);
                    <div className="row">
                        <div className={`col-md-8 offset-md-2 col-xl-4 offset-xl-4 ${classes.projectChoice}`}>
                            <ProjectChoice selectedClient={this.state.selectedClient} selectedProject={this.state.selectedProject} changed={this.handleProjectChoice} />
                        </div>
                    </div>
                    <div className="row">
                        <div className={`col-12 ${classes.mainPanel}`}>
                            <ProjectInfo key={this.state.selectedProject} selectedProject={this.state.selectedProject} />
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

ProjectChoice component

const ProjectChoice = (props) => {
    const selectedClient = parseInt(props.selectedClient);
    // const [selectedClient,setSelectedClient] = useState(props.selectedClient); => I tried this as well...

    console.log("selectedClient in ProjectChoice");
    console.log(selectedClient); // shows updated value

    useEffect(() => {
        console.log("In useEffect"); // does not appear => not triggered when component is re rendered
        userService.getById(selectedClient)
            .then(response => {
                console.log(response);
            });
    },[]);

    return (
        // THIS IS NOT RELEVANT
    );
};

Upvotes: 1

Views: 154

Answers (2)

wesley.buijsman
wesley.buijsman

Reputation: 46

Your useEffect has an empty dependency array, which means it only fires on the first render. If you want it to fire again when a dependency changes, add the dependency to the array so the useEffect fires whenever that dependency changes. So in your case the dependency would be selectedClient.

useEffect(() => {
    console.log("In useEffect"); // does not appear => not triggered when component is re rendered
    userService.getById(selectedClient)
        .then(response => {
            console.log(response);
        });
},[selectedClient]);

More info in the official documentation about useEffect optimization.

Upvotes: 2

Sarun UK
Sarun UK

Reputation: 6736

Try this approach,

useEffect(() => {
    console.log("In useEffect"); // does not appear => not triggered when component is re rendered
    userService.getById(selectedClient)
        .then(response => {
            console.log(response);
        });
},[selectedClient]);

Upvotes: 1

Related Questions