Search code examples
reactjsreact-nativerxjsobserver-pattern

View not being updated after setting state with subscriber


I am having this weird problem where my component is not updating its view after the state is being set. In the view, a bunch of text components get rendered using the values inside the payments array state.

const Payments: (props: Props) => any = (props: Props): JSX.Element => {
const [payments, setPayments] = useState<Array<number>>([]);

useEffect(() => {
    PaymentsService.payments.subscribe((value: Array<number>) => {
        console.log(`State being set with the following value:`);
        console.log(value);
        setPayments(value);
    })
});

const array = payments.map(p => {
    return <Text>{`${p}`}</Text>
});

console.log("New text array:");
console.log(array);

const handleOnPress = () => {
    PaymentsService.addPayment();
};

return (
    <View style={ props.themedStyle!.container }>
        <Text>This is the payments page.</Text>
        {array}
        <Button onPress={handleOnPress}/>
    </View>
  );
};

When the payments in the PaymentsService change, the subscriber gets notified with the new value, and then uses setPayments to set the state with the new value.

import { BehaviorSubject } from "rxjs";

const initialPayments: Array<number> = [ 34, 43, 114, 43 ];
const payments: BehaviorSubject<Array<number>> = new BehaviorSubject<Array<number>>(initialPayments);

const addPayment = () => {
    const newPayments = payments.getValue();
    newPayments.push(Math.random() * 100);
    payments.next(newPayments);
};

export default {
    payments,
    addPayment
}

When I add a new payment, the payments array in PaymentsService gets updated. Then the subscriber in the view gets notified with the correct values.

I don't understand what is preventing the view from updating, if its get supplied with new values?


Solution

  • I have found the problem. React still thinks the new state is the same as the previous state, hence it is not being rendered again.

    In order to have it render with the new data, I need to return a NEW array. So in this case I cannot simply use the value of payments.getValue() and push another number on it. I need to create a new array out of it.