redux 官方示例 todomvc 两个警告修复

题外话:
本人有轻度代码洁癖,只要有警告,我会认为代码还有需要完善的地方,只要有时间我就会着手去解决它,去了解其背后的原因,了解为什么会发出警告,以及解决方案是什么,最终消除这些影响代码质量的“隐患”。
通过解决这类问题,会让自己对相关代码的理解更加深入,做到知其然,并且知其所以然,同时,能够让自己对相关知识点印象深刻。

两个警告相关的 PR

备注:PR 合并之后,最新版已经没有这两个警告了

官方 todomvc 示例源码

其实改动很小,主要看解决思路和理解相关的知识点。

两个大大的红色警告

examples/todomvc/src/components/TodoTextInput.js

完整警告信息如下:

Warning: Received the string `true` for the boolean attribute `autoFocus`. Although this works, 
it will not work as expected if you pass the string "false". Did you mean autoFocus={true}?
    in input (at TodoTextInput.js:40)
    in TodoTextInput (at Header.js:8)
    in header (at Header.js:6)
    in Header (created by Connect(Header))
    in Connect(Header) (at App.js:7)
    in div (at App.js:6)
    in App (at src/index.js:13)
    in Provider (at src/index.js:12)

解决

上面的提示信息,其实已经非常友好了,看重点:Did you mean autoFocus={true}?
看一下报错的地方的源码(TodoTextInput.js:40

  <input className={
    classnames({
      edit: this.props.editing,
      'new-todo': this.props.newTodo
    })}
    type="text"
    placeholder={this.props.placeholder}
    autoFocus="true"
    value={this.state.text}
    onBlur={this.handleBlur}
    onChange={this.handleChange}
    onKeyDown={this.handleSubmit} />

根据友好的提示信息,将上面的 autoFocus="true" 改为 autoFocus={true} 即可。

examples/todomvc/src/components/MainSection.js

完整警告信息如下:

index.js:1452 Warning: Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. 
This will render a read-only field. 
If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.
    in input (at MainSection.js:12)
    in span (at MainSection.js:11)
    in section (at MainSection.js:8)
    in MainSection (created by Connect(MainSection))
    in Connect(MainSection) (at App.js:8)
    in div (at App.js:6)
    in App (at src/index.js:13)
    in Provider (at src/index.js:12)

看一下报错的地方的源码(MainSection.js:12

  <input
    className="toggle-all"
    type="checkbox"
    checked={completedCount === todosCount}
  />

从下面的提示信息看

You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field.

我的理解是:设置了 checked 属性,但是又没有提供 onChange 事件来更新它,那么,将会自动为其设置一个 read-only 属性。
将上面的代码,去掉 className 属性,如下:

  <input
    type="checkbox"
    checked={completedCount === todosCount}
  />

再看界面,这时候,一个可以看到是否选中状态的复选框出现了,它确实是只读的,点击没有反应,当所有待办事项变成完成状态时,该 checkbox 会被设置为选中状态,否则为非选中状态。
再看后面的提示:

If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly` 

我的理解是:如果该 checkbox 是可变的,那么,请为其设置一个默认值,否则,要么设置 onChange 事件,要么设置 readOnly 属性。
设置默认值,例如设置默认选中,可以这样:

  <input
    type="checkbox"
    defaultChecked={true}
  />

如果为其设置默认值 defaultChecked,但不动态设置 checked 属性,是不会有上面的警告的,但我们需要动态为其设置 checked 属性,这样在界面上能看出来是否为全部选中状态(向下的箭头颜色有差别,更详细的,请运行起来查看实际效果)。

很明显,如果要为其设置 checked 属性,设置 defaultChecked 是没有意义的(即使设置了,也还是会报同样的警告)。
所以,从提示信息看上,为了消除这个警告,有两种解决办法:

  1. 设置 readOnly 属性。
      <input
        type="checkbox"
        defaultChecked={completedCount === todosCount}
        readOnly
      />
    
  2. 设置一个 onChange 事件,哪怕是一个什么也不做的“空”事件。
      <input
        type="checkbox"
        defaultChecked={completedCount === todosCount}
        onChange={()=>{}}
      />
    

对于这个例子,设置 readOnly 是最好的方案,本来也是需要只读的嘛。设置“空”事件有点莫名其妙。

解读第二个警告

至于为什么 react 会有这样的检查,stackoverflow.com 网站上有一个网友的回答,我认为是比较贴切的,摘录如下:

Controlled Components

Attributes needed:

  1. value - <input> (not checkbox or radio), <select>, <textbox> or checked for (checkbox or radio).
  2. onChange
  • React handles the condition of the element by updating the value or checked attribute (depending on the element) from the props or the state.
  • We need to notify react when we make a change, like inserting data, or checking the box,
  • so react can update the element’s condition when it rerenders the component.
  • To do so, we must include an onChange handler, in which we will update the state or notify the component’s parent, so it will update the props.
<input
  type="checkbox"
  checked={ this.props.checked }
  onChange={ this.checkboxHandler } 
/>

Uncontrolled Components

Attributes needed:

defaultValue - <input> (not checkbox or radio), <select>, <textbox> or defaultChecked for (checkbox or radio).

React sets the initial value using defaultValue or defaultChecked, and the update of the element’s state is controlled by the user, usually via the DOM using refs.

<input
  type="checkbox"
  defaultChecked={ this.props.checked } 
/>

扩展阅读

是有关可控组件和非可控组件的。

关于作者

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redux中,可以使用combineReducers函数将多个独立的reducers合并成一个reducer,从而使它们联系起来。combineReducers函数接受一个对象作为参数,对象中的每个属性都是一个独立的reducer函数,combineReducers函数会将这些reducer函数合并成一个新的reducer函数,当action被dispatch时,它会遍历所有的reducer函数,执行它们并返回新的state对象。 举个例子,假设我们有两个独立的reducers,一个处理用户信息,另一个处理购物车信息,我们可以将它们合并成一个reducer并将它作为createStore函数的参数: ``` import { combineReducers, createStore } from 'redux'; // 用户信息reducer function userReducer(state = {}, action) { switch (action.type) { case 'SET_USER_NAME': return { ...state, name: action.payload }; default: return state; } } // 购物车信息reducer function cartReducer(state = [], action) { switch (action.type) { case 'ADD_TO_CART': return [...state, action.payload]; default: return state; } } // 合并reducer const rootReducer = combineReducers({ user: userReducer, cart: cartReducer }); // 创建store const store = createStore(rootReducer); ``` 在上面的例子中,我们将两个独立的reducers合并成了一个rootReducer,并将它作为createStore函数的参数来创建store。当我们dispatch一个action时,rootReducer会遍历所有的reducers,执行它们并返回新的state对象。例如: ``` store.dispatch({ type: 'SET_USER_NAME', payload: 'Alice' }); store.dispatch({ type: 'ADD_TO_CART', payload: { id: 1, name: 'Product A' } }); ``` 这样,我们就可以在一个action中同时更新用户信息和购物车信息,并且这两个reducers之间也可以互相访问彼此的state。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值