Search code examples
reactjstypescriptreact-nativereact-propsreact-children

React native child not receiving updated props value


I am new to react and making a little app to learn the library and way of thinking.
But I ran into a problem which has me completely stomped...

I have the root components that contains a list of tasks. I pass these tasks to a custom component to render them into a groups like so:
<TasksView tasks={this.state.tasks}></TasksView>
Where this.state.tasks is an array containing all the current tasks.

But the problem is that my TaskView component never seems to receive these tasks...

See below for the complete code:

ROOT:

class App extends Component<{}, IAppState> {

    constructor(props: any) {
        super(props);

        this.state = {
            taskCategories: [],
            tasks: [],
            currentTask: {}
        };
    }

    testing() {
        this.setState((prev: IAppState) => {
            return {
                tasks: [...prev.tasks, {
                    index: 0,
                    timespan: [TimeTypes.Day, TimeTypes.Week, TimeTypes.Month, TimeTypes.Year][Math.round(Math.random() * 9)],
                    name: '',
                    repeatAmount: 0,
                    repeatDelay: 0,
                    category: {
                        id: 0,
                        color: "",
                        name: ""
                    },
                    onComplete: function (index: number): void {
                        throw new Error('Function not implemented.');
                    }
                }]
            }
        });
    }


    render() {
        console.log("tasks count in parent: ", this.state.tasks.length); //<-- console.log A
        return (
            <SafeAreaView style={styles.container}>
                <TasksView tasks={this.state.tasks}></TasksView>
                <TouchableOpacity
                    onPress={this.testing.bind(this)}
                    style={styles.createTask}
                >
                </TouchableOpacity>
            </SafeAreaView>
        )
    }
};

TASKSVIEW:

class TasksView extends Component<TasksViewProps, any> {

    taskGroups: TasksGroupData[];
    stickyIndices: number[];

    constructor(props: TasksViewProps) {
        super(props);

        console.log("props should be updated..."); //<-- console.log B
        console.log(props.tasks.length);           //<-- console.log C

        this.taskGroups = [];
        this.stickyIndices = [];
    }

    render(): ReactNode {
        return [
            <Text style={tasksViewStyle.title}>Your Goals</Text>,
            <ScrollView
                stickyHeaderIndices={this.stickyIndices}
                showsVerticalScrollIndicator={false}
                style={tasksViewStyle.scrollView}
            >
                {this.taskGroups.map((group: TasksGroupData, index: number) =>
                    <TasksGroup key={index} timespan={group.timespan} tasks={group.tasks}></TasksGroup>
                )}
            </ScrollView>
        ];
    }
}

I have left out all the interface definitions and some helper functions since they would not be relevant to the problem at hand.

So what i would expect is every time console.log A gets executed console.log B and C would also be executed but this is not the case.
See here a screenshot of current console.log sequence.
enter image description here

If any additional information is required let me know so I can update the question.


Solution

  • The constructor is only run once when your component is first mounted, because React re-uses the same class instance for the lifetime of the component (see these docs). This is why you're not seeing your logging calls after they are initially run once.

    For logging that runs on each render, you could move your console.logs into componentDidUpdate.