mobx react inject 理解

在學(xué)習(xí)mobx中,遇到一個(gè)難題弄了幾小時(shí)也沒搞明白inject,雖然知道這是注入,但不知道正確用法,還是很傷腦筋的。

為了簡單的理解所以文件我沒有分開管理,也寫在同一個(gè)文件里方便查看,
項(xiàng)目建立使用creact-react-app,所以App.js是什么就不多說了。

在不使用inject的時(shí)候以下代碼都是可以正常運(yùn)行的。

App.js

import React, { Component } from 'react';
import './App.css';
import { observable, computed } from 'mobx';
import { observer,Provider,inject } from 'mobx-react'


//數(shù)據(jù)結(jié)構(gòu)
class Todo {
    @observable todos = [
        {
            id: 1,
            title: '任務(wù)1',
            finished: false
        }, {
            id: 2,
            title: '任務(wù)2',
            finished: false
        }
    ];

    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}


@observer
class TodoListView extends Component {
    render() {
        return (
            <div>
                <ul>
                    {this.props.todoList.todos.map(todo =>
                        <TodoView todo={todo} key={todo.id}/>
                    )}
                </ul>
                未完成任務(wù)數(shù):{this.props.todoList.unfinishedTodoCount}
            </div>
        )

    }
}

@observer
class TodoView extends Component {
    componentWillReact() {
        console.log('I will re-render, since the todo has changed!');

    }

    render() {
        // return <div>{this.props.todo.title}</div>;
        var todo = this.props.todo;
        return (
            <li>
                <label>
                    <input
                        type="checkbox"
                        checked={todo.finished}
                        onClick={() => todo.finished = !todo.finished}
                    />

                    {todo.title}
                </label>
            </li>
        )
    }

}

const todoList = new Todo();



class App extends Component{
    render(){
        return (
            <div>
                <TodoListView todoList={todoList}/>
            </div>

        );
    }
}
export default App;

通過簡單的修改對App添加了inject,修改后的代碼如下:

//以上代碼不變,

@inject('todoList')
class App extends Component{
    render(){
        return (
            <div>
                <TodoListView todoList={this.props.todoList}/>
            </div>

        );
    }
}

你會(huì)看到以下報(bào)錯(cuò)信息:
Error: MobX injector: Store 'todoList' is not available! Make sure it is provided by some Provider

從報(bào)錯(cuò)信息可以知道需要一個(gè)Provider
于是傻傻的寫下以下代碼:


@inject('todoList')
class App extends Component{
    render(){
        return (
            <Provider>
            <div>
                <TodoListView todoList={this.props.todoList}/>
            </div>
            </Provider>

        );
    }
}

但還是報(bào)同樣的錯(cuò)誤信息,這個(gè)頭大了,不知道怎么搞了。唯一的辦法就是冷靜下來,認(rèn)真思考

在好好思考后發(fā)現(xiàn)問題所在:injector本身需要一個(gè)Provider,我又把寫到inject里面,這完全沒有用的,看來是寫反了,應(yīng)該是一個(gè)Provider為根才對。想清楚這點(diǎn)后,開始改造。

@inject('todoList')
class ToDoApp extends Component{
    render(){
        return (
            <div>
                <TodoListView todoList={this.props.todoList}/>
            </div>
        );
    }
}

class App extends Component{
    render(){
        return(
            <Provider todoList={todoList}>
                <ToDoApp/>
            </Provider>
        )
    }
}

嘗試一下成功了,^_^。
完整代碼如下:

import React, { Component } from 'react';
import './App.css';
import { observable, computed } from 'mobx';
import { observer,Provider,inject } from 'mobx-react'


//數(shù)據(jù)結(jié)構(gòu)
class Todo {
    @observable todos = [
        {
            id: 1,
            title: '任務(wù)1',
            finished: false
        }, {
            id: 2,
            title: '任務(wù)2',
            finished: false
        }
    ];

    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}


@observer
class TodoListView extends Component {
    render() {
        return (
            <div>
                <ul>
                    {this.props.todoList.todos.map(todo =>
                        <TodoView todo={todo} key={todo.id}/>
                    )}
                </ul>
                未完成任務(wù)數(shù):{this.props.todoList.unfinishedTodoCount}
            </div>
        )

    }
}

@observer
class TodoView extends Component {
    componentWillReact() {
        console.log('I will re-render, since the todo has changed!');

    }

    render() {
        // return <div>{this.props.todo.title}</div>;
        var todo = this.props.todo;
        return (
            <li>
                <label>
                    <input
                        type="checkbox"
                        checked={todo.finished}
                        onClick={() => todo.finished = !todo.finished}
                    />

                    {todo.title}
                </label>
            </li>
        )
    }

}

const todoList = new Todo();



@inject('todoList')
class ToDoApp extends Component{
    render(){
        return (
            <div>
                <TodoListView todoList={this.props.todoList}/>
            </div>
        );
    }
}

class App extends Component{
    render(){
        return(
            <Provider todoList={todoList}>
                <ToDoApp/>
            </Provider>
        )
    }
}


export default App;

想了想,如果不使用inject全是什么情況呢?

// @inject('todoList')
class ToDoApp extends Component{
    render(){
        return (
            <div>
                <TodoListView todoList={this.props.todoList}/>
            </div>
        );
    }
}

class App extends Component{
    render(){
        return(
            <Provider>
                <ToDoApp todoList={todoList}/>
            </Provider>
        )
    }
}

通過修改不難發(fā)現(xiàn)

  1. Provider為根
  2. 如果不使用Provider配合inject的話,代碼相對多一些,需要自己的管理
  3. 如果使用Provider配合inject,就沒有那么麻煩了,把多個(gè)store,配到根上,子組件通過inject自動(dòng)注入。

以下為簡單應(yīng)用:

import React, { Component } from 'react';
import './App.css';
import { observable, computed } from 'mobx';
import { observer,Provider,inject } from 'mobx-react'


//數(shù)據(jù)結(jié)構(gòu)
class Todo {
    @observable todos = [
        {
            id: 1,
            title: '任務(wù)1',
            finished: false
        }, {
            id: 2,
            title: '任務(wù)2',
            finished: false
        }
    ];

    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}


@observer
class TodoListView extends Component {
    delClick = (todo)=>{ 
      this.props.todoList.todos.remove(todo);
    };
    render() {

        return (
            <div>
                <ul>
                    {this.props.todoList.todos.map(todo =>
                        <TodoView todo={todo} delClick={this.delClick} key={todo.id}/>
                    )}
                </ul>
                未完成任務(wù)數(shù):{this.props.todoList.unfinishedTodoCount}
            </div>
        )

    }
}

@observer
class TodoView extends Component {
    componentWillReact() {
        console.log('I will re-render, since the todo has changed!');

    }
    render() {
        var todo = this.props.todo;
        return (
            <li>
                <label>
                    <input
                        type="checkbox"
                        checked={todo.finished}
                        onClick={() => todo.finished = !todo.finished}
                    />

                    {todo.title}
                </label>
                <button onClick={() => {this.props.delClick(todo)}}>del</button>
            </li>
        )
    }

}

const todoList = new Todo();



@inject('todoList')
class ToDoApp extends Component{
    render(){
        return (
            <div>
                <TodoListView todoList={this.props.todoList}/>
            </div>
        );
    }
}

@inject('todoList')
@observer
class ToDoAdd extends Component{
    todoList = this.props.todoList;
    add=()=>{

        const title = this.refs.task.value;

        if(!title.length){
            alert('任務(wù)名字不能為空');
            return;
        }
        todoList.todos.push({
            id: 3, //臨時(shí)
            title: this.refs.task.value,
            finished: false
        })
    };
    render(){
        return(
            <div>
                <input type="text" ref='task'/>
                <button onClick={this.add}>添加</button>
            </div>
        )
    }
}


class App extends Component{
    render(){
        return(
            <Provider todoList={todoList}>
                <div>
                    <ToDoAdd />
                    <ToDoApp />
                </div>
            </Provider>
        )
    }
}


export default App;

6E0269DC-9114-4F78-A575-8B7FDA65DEDA.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • core package 概要:Core是所有其他包的基礎(chǔ)包.它提供了大部分功能包括metadata,templa...
    LOVE小狼閱讀 2,891評論 0 3
  • 此文為本人學(xué)習(xí)guice的過程中,翻譯的官方文檔,如有不對的地方,歡迎指出。另外還有一些附件說明、吐槽、疑問點(diǎn),持...
    李眼鏡閱讀 3,656評論 2 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • 看了《萬歷十五年》,很多感慨。這本書是用隨筆形式寫的,沒有跌宕起伏的歷史故事,有的只是將歷史事件娓娓道來,然后再其...
    鳳舞清林閱讀 261評論 0 0
  • 質(zhì)疑自己的工具 很長時(shí)間以來,自己也沉醉于各種的捷徑以及愛好儲(chǔ)存各種資料,“21天速成XX”,“提高效率的4個(gè)小插...
    大食量高級會(huì)漲閱讀 460評論 0 1

友情鏈接更多精彩內(nèi)容