mobx react inject 理解

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

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

在不使用inject的時候以下代碼都是可以正常運行的。

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>

        );
    }
}

你會看到以下報錯信息:
Error: MobX injector: Store 'todoList' is not available! Make sure it is provided by some Provider

從報錯信息可以知道需要一個Provider
于是傻傻的寫下以下代碼:


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

        );
    }
}

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

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

@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,就沒有那么麻煩了峻黍,把多個store复隆,配到根上,子組件通過inject自動注入姆涩。

以下為簡單應(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, //臨時
            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)系作者
  • 序言:七十年代末挽拂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子骨饿,更是在濱河造成了極大的恐慌亏栈,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宏赘,死亡現(xiàn)場離奇詭異绒北,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)察署,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門镇饮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事储藐【慵茫” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵钙勃,是天一觀的道長蛛碌。 經(jīng)常有香客問我,道長辖源,這世上最難降的妖魔是什么蔚携? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮克饶,結(jié)果婚禮上酝蜒,老公的妹妹穿的比我還像新娘。我一直安慰自己矾湃,他們只是感情好亡脑,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著邀跃,像睡著了一般霉咨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拍屑,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天途戒,我揣著相機(jī)與錄音,去河邊找鬼僵驰。 笑死喷斋,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蒜茴。 我是一名探鬼主播继准,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矮男!你這毒婦竟也來了移必?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤毡鉴,失蹤者是張志新(化名)和其女友劉穎崔泵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猪瞬,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡憎瘸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了陈瘦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幌甘。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锅风,到底是詐尸還是另有隱情酥诽,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布皱埠,位于F島的核電站肮帐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏边器。R本人自食惡果不足惜训枢,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望忘巧。 院中可真熱鬧恒界,春花似錦、人聲如沸砚嘴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枣宫。三九已至,卻和暖如春吃环,著一層夾襖步出監(jiān)牢的瞬間也颤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工郁轻, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留翅娶,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓好唯,卻偏偏與公主長得像竭沫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子骑篙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • core package 概要:Core是所有其他包的基礎(chǔ)包.它提供了大部分功能包括metadata蜕提,templa...
    LOVE小狼閱讀 2,559評論 0 3
  • 此文為本人學(xué)習(xí)guice的過程中,翻譯的官方文檔靶端,如有不對的地方谎势,歡迎指出。另外還有一些附件說明杨名、吐槽脏榆、疑問點,持...
    李眼鏡閱讀 3,484評論 2 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理台谍,服務(wù)發(fā)現(xiàn)须喂,斷路器,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • 本文將開始詳細(xì)分析如何搭建一個React應(yīng)用架構(gòu)。 一. 前言 現(xiàn)在已經(jīng)有很多腳手架工具坞生,如create-reac...
  • 看了《萬歷十五年》仔役,很多感慨。這本書是用隨筆形式寫的恨胚,沒有跌宕起伏的歷史故事骂因,有的只是將歷史事件娓娓道來,然后再其...
    鳳舞清林閱讀 171評論 0 0