I’ve created a MobX store (React Native project) and am updating a state value on button click. The state is successfully updating as displayed in a console log, but the DOM is not re-rendering with the updated state.
Most answers on SO are a little outdated as they recommend adding @observable
in the right places, but the latest MobX docs say to use a different syntax with makeAutoObservable(this, { key: value })
.
(EDIT: Codesandbox so you can see in Home.js the console logging on button press, but “You love…” not updating with mobx store value)
Here’s my current set up:
store.js
import { makeAutoObservable, observable } from "mobx"; export class ChooseTea { tea; constructor() { makeAutoObservable(this, { tea: observable, }); } selectTea = (tea) => { this.tea = tea; }; }
Home.js
import { ChooseTea } from "../data/store"; import { observer } from "mobx-react"; export const Home = observer(() => { const store = new ChooseTea(); const handleChildChoose = (tea) => { store.selectTea(tea); // value passed to store console.log(store.tea); // successfully logs the new chosen tea }; return ( <View style={styles.container}> <Text>You love {store.tea}</Text> // does not update on new tea chosen <View style={styles.teaCardContainer}> {teaData && teaData.map((teaObj) => ( <TeaCard id={teaObj.id} teaData={teaObj} key={teaObj.id} strength={teaStrength * 2} handleChoose={handleChildChoose} /> ))} </View> </View> ); });
TeaCard.js
function TeaCard({ teaData, handleChoose }) { const handleClick = (tea) => { handleChoose(tea); // value passed to parent component (Home.js) }; return ( <View> <View> <Text>{teaData.name}</Text> </View> <Rating count={teaData.rating} /> <Button title="Choose" onPress={() => handleClick(teaData.name)} color={AppStyles.colour.secondary} /> </View> ) }
Advertisement
Answer
This line is the problem:
const store = new ChooseTea();
You are recreating you store on every render. Your component actually react to changes, starts rerendering, but then new store is created and tea
is not selected there by default. So you are changing data in your old store, but then use data from newly created one.
What you can do is use useState
or useMemo
for your store, like that:
const [store] = useState(() => new ChooseTea());
You also need to define all your properties, it won’t work otherwise (or at least without extra configuration):
export class ChooseTea { // Use null or empty string "", for example tea = null; constructor() { makeAutoObservable(this); } selectTea = (tea) => { this.tea = tea; }; }