reactjs - komponenten renderas inte om när tillståndet uppdateras i mobx


Jag försöker förstå varför min app inte renderar om när jag ändrar mitt state i mobx-observable-namn arrayen. Jag ändrar värdet med input-taggen. Skulle uppskatta lite hjälp :)

observatörskomponent:

import {observable, action, autorun, computed} from 'mobx'

class TodosStore {
    @observable names = ["p1", "p2", "p3"]
    @observable filter = ""

    @action
    get filterredValue(){
        return store.names.filter(word => word.includes(this.filter))
    }
}

//@ts-ignore
var store = window.store = new TodosStore

export default store


autorun(() => {
    console.log(store.filter); 
    console.log(store.names); 
})

och detta är min appkomponent:

import React from 'react';
import './App.css';
import store from  './components/observers'

class App extends React.Component {
  constructor(props :any) {
    super(props);
    this.setName = this.setName.bind(this);
  }

  setName = (e : any) => {
    store.filter = e.target.value

  }

  render() {
  return (
    <div className="App">
      <header className="App-header">
        {store.filterredValue.map((name) => <li key={name}>{name}</li>)}
        <input
          onChange={(e) => this.setName(e)}
          />
      </header>
    </div>
  );
}
}

export default App;

Svar #1

Först och främst behöver du omsluta varje komponent som använder observable-tillstånd med observer-dekoreraren, så här:

import {observer} from 'mobx-react'

@observer
class App extends React.Component {
  // ...
}

// or if you are using functional components:

const App = observer(() => {
  // ...
})

Dessutom, om du använder MobX version 6 behöver du lägga till anropet makeObservable inuti klasskonstruktorn:

import {observable, action, autorun, computed, makeObservable} from 'mobx'

class TodosStore {
    @observable names = ["p1", "p2", "p3"]
    @observable filter = ""

    constructor() {
       makeObservable(this);
    }

    @action
    get filterredValue(){
        return store.names.filter(word => word.includes(this.filter))
    }
}

Mer om MobX och React-integrering i dokumentationen

Svar #2

Du kan definiera saker som observable, computed och action i TodoStore med makeObservable eftersom decorators för närvarande inte föredras (decorators är för närvarande inte en ES-standard, och standardiseringsprocessen tar lång tid):

TodoStore:

import { observable, autorun, computed, makeObservable, action } from "mobx";

class TodoStore {
  names = ["p1", "p2", "p3"];
  filter = "";

  constructor() {
    makeObservable(this, {
      names: observable,
      filter: observable,
      filterredValue: computed,
      setFilter: action,
    });
    autorun(() => {
      console.log(this.filter);
      console.log(this.names);
    });
  }

  get filterredValue() {
    return this.names.filter((word) => word.includes(this.filter));
  }

  setFilter(filter) {
    this.filter = filter;
  }
}

export const todoStore = new TodoStore();

Och här är App-komponenten som använder observer (En högre ordningskomponent som gör en funktionell eller klassbaserad React-komponent omrenderad när observabler ändras):

App:

import { observer } from "mobx-react";
import { Component } from "react";

class App extends Component<any> {
  setName = (e: React.ChangeEvent<HTMLInputElement>) => {
    this.props.store.setFilter(e.target.value);
  };

  render() {
    return (
      <div className="App">
        <header className="App-header">
          {this.props.store.filterredValue.map((name) => (
            <li key={name}>{name}</li>
          ))}
          <input onChange={(e) => this.setName(e)} />
        </header>
      </div>
    );
  }
}

export default observer(App);

Demo:

Relaterade artiklar