題外話:
本人有輕度代碼潔癖,只要有警告,我會(huì)認(rèn)為代碼還有需要完善的地方,只要有時(shí)間我就會(huì)著手去解決它,去了解其背后的原因,了解為什么會(huì)發(fā)出警告,以及解決方案是什么,最終消除這些影響代碼質(zhì)量的“隱患”。
通過(guò)解決這類問(wèn)題,會(huì)讓自己對(duì)相關(guān)代碼的理解更加深入,做到知其然,并且知其所以然,同時(shí),能夠讓自己對(duì)相關(guān)知識(shí)點(diǎn)印象深刻。
備注:PR 合并之后,最新版已經(jīng)沒(méi)有這兩個(gè)警告了
其實(shí)改動(dòng)很小,主要看解決思路和理解相關(guān)的知識(shí)點(diǎn)。

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)
解決
上面的提示信息,其實(shí)已經(jīng)非常友好了,看重點(diǎn):Did you mean autoFocus={true}?
看一下報(bào)錯(cuò)的地方的源碼(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} />
根據(jù)友好的提示信息,將上面的 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)
看一下報(bào)錯(cuò)的地方的源碼(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.
我的理解是:設(shè)置了 checked 屬性,但是又沒(méi)有提供 onChange 事件來(lái)更新它,那么,將會(huì)自動(dòng)為其設(shè)置一個(gè) read-only 屬性。
將上面的代碼,去掉 className 屬性,如下:
<input
type="checkbox"
checked={completedCount === todosCount}
/>
再看界面,這時(shí)候,一個(gè)可以看到是否選中狀態(tài)的復(fù)選框出現(xiàn)了,它確實(shí)是只讀的,點(diǎn)擊沒(méi)有反應(yīng),當(dāng)所有待辦事項(xiàng)變成完成狀態(tài)時(shí),該 checkbox 會(huì)被設(shè)置為選中狀態(tài),否則為非選中狀態(tài)。
再看后面的提示:
If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`
我的理解是:如果該 checkbox 是可變的,那么,請(qǐng)為其設(shè)置一個(gè)默認(rèn)值,否則,要么設(shè)置 onChange 事件,要么設(shè)置 readOnly 屬性。
設(shè)置默認(rèn)值,例如設(shè)置默認(rèn)選中,可以這樣:
<input
type="checkbox"
defaultChecked={true}
/>
如果為其設(shè)置默認(rèn)值 defaultChecked,但不動(dòng)態(tài)設(shè)置 checked 屬性,是不會(huì)有上面的警告的,但我們需要?jiǎng)討B(tài)為其設(shè)置 checked 屬性,這樣在界面上能看出來(lái)是否為全部選中狀態(tài)(向下的箭頭顏色有差別,更詳細(xì)的,請(qǐng)運(yùn)行起來(lái)查看實(shí)際效果)。
很明顯,如果要為其設(shè)置 checked 屬性,設(shè)置 defaultChecked 是沒(méi)有意義的(即使設(shè)置了,也還是會(huì)報(bào)同樣的警告)。
所以,從提示信息看上,為了消除這個(gè)警告,有兩種解決辦法:
- 設(shè)置 readOnly 屬性。
<input type="checkbox" defaultChecked={completedCount === todosCount} readOnly /> - 設(shè)置一個(gè) onChange 事件,哪怕是一個(gè)什么也不做的“空”事件。
<input type="checkbox" defaultChecked={completedCount === todosCount} onChange={()=>{}} />
對(duì)于這個(gè)例子,設(shè)置 readOnly 是最好的方案,本來(lái)也是需要只讀的嘛。設(shè)置“空”事件有點(diǎn)莫名其妙。
解讀第二個(gè)警告
至于為什么 react 會(huì)有這樣的檢查,stackoverflow.com 網(wǎng)站上有一個(gè)網(wǎng)友的回答,我認(rèn)為是比較貼切的,摘錄如下:
Controlled Components
Attributes needed:
value - <input> (not checkbox or radio), <select>, <textbox> or checked for (checkbox or radio).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 }
/>
擴(kuò)展閱讀
是有關(guān)可控組件和非可控組件的。
關(guān)于作者
- github: https://github.com/uncleAndyChen
- gitee: https://gitee.com/uncleAndyChen
- 個(gè)人博客:https://www.lovesofttech.com
- CSDN博客:https://blog.csdn.net/runAndRun
- 郵箱:andy@lovesofttech.com