React曾经忽略的知识点(下)
1.JSX渲染
想让类似 false
、true
、null
或 undefined
出现在输出中,你必须先把它转换成字符串 :
<div> My JavaScript variable is {String(myVariable)}. </div>
2.获取上传文件的信息
class FileInput extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { event.preventDefault(); alert( `Selected file - ${this.fileInput.files[0].name}` ); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Upload file: <input type="file" ref={input => { this.fileInput = input; }} /> </label> <br /> <button type="submit">Submit</button> </form> ); } } ReactDOM.render( <FileInput />, document.getElementById('root') );
3.防止突变,添加数组的方法
1.用concat
重写成
handleClick() {
this.setState(prevState => ({
words: prevState.words.concat(['marklar'])
}));
}
2.用ES6支持数组的spread语法
handleClick() {
this.setState(prevState => ({
words: [...prevState.words, 'marklar'],
}));
};
function updateColorMap(colormap) {
return {...colormap, right: 'blue'};
}
3.不污染原始对象,使用Object.assign方法
function updateColorMap(colormap) {
return Object.assign({}, colormap, {right: 'blue'});
}
updateColorMap
现在会返回一个新对象,而不会改变之前的旧对象。Object.assign
在ES6中,需要polyfill
支持。
如果使用Create React App
,默认情况下 Object.assign
和spread对象都可以使用。
4.Context
Context 设计目的是为共享那些被认为对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。
1.React.createContext
const {Provider, Consumer} = React.createContext(defaultValue);
创建一对 { Provider, Consumer }
。当 React 渲染 context 组件 Consumer 时,它将从组件树的上层中最接近的匹配的 Provider 读取当前的 context 值。
如果上层的组件树没有一个匹配的 Provider,而此时你需要渲染一个 Consumer 组件,那么你可以用到 defaultValue
。这有助于在不封装它们的情况下对组件进行测试。
2.Provider
<Provider value={/* some value */}>
React 组件允许 Consumers 订阅 context 的改变。
接收一个 value
属性传递给 Provider 的后代 Consumers。一个 Provider 可以联系到多个 Consumers。Providers 可以被嵌套以覆盖组件树内更深层次的值。
3.Consumer
<Consumer> {value => /* render something based on the context value */} </Consumer>
一个可以订阅 context 变化的 React 组件。
接收一个 函数作为子节点. 函数接收当前 context 的值并返回一个 React 节点。传递给函数的 value
将等于组件树中上层 context 的最近的 Provider 的 value
属性。如果 context 没有 Provider ,那么 value
参数将等于被传递给 createContext()
的 defaultValue
。
注意
每当Provider的值发送改变时, 作为Provider后代的所有Consumers都会重新渲染。 从Provider到其后代的Consumers传播不受shouldComponentUpdate方法的约束,因此即使祖先组件退出更新时,后代Consumer也会被更新。
举个例子:
index.js
import React, { Component } from 'react'; import {ThemeContext,themes,UserContext} from './theme-context'; import ThemeTogglerButton from './theme-toggler-button' function Toolbar(props){ return( <ThemeContext.Consumer> {({theme,toggleTheme})=>( <UserContext.Consumer> {user=>( <ThemeTogglerButton user={user} theme={theme} toggleTheme={toggleTheme}/> )} </UserContext.Consumer> )} </ThemeContext.Consumer> ); } class LotsContext extends Component { constructor(props){ super(props); this.toggleTheme = ()=>{ this.setState(state=>({ theme: state.theme === themes.purple ?themes.pink :themes.purple, })); }; this.state={ theme:themes.pink, toggleTheme:this.toggleTheme, user:'mosquito~' }; } render() { const {user,theme,toggleTheme} = this.state; return ( <ThemeContext.Provider value={{theme,toggleTheme}}> <UserContext.Provider value={user}> <Toolbar /> </UserContext.Provider> </ThemeContext.Provider> ); } } export default LotsContext;
theme-context.js
import React from 'react';
export const themes = {
pink:{
background:"pink",
},
purple:{
background:"purple",
},
};
export const ThemeContext = React.createContext({
theme:themes.pink,
toggleTheme:()=>{},
});
export const UserContext = React.createContext({
user:"mosquito~"
});
theme-toggler-button.js
import React from 'react'; import {ThemeContext} from './theme-context'; function ThemeTogglerButton(props){ return( <ThemeContext.Consumer> {({theme,toggleTheme}) => ( <div onClick={toggleTheme} style={{width:'100px',height:'100px',backgroundColor: theme.background}} > {props.user} </div> )} </ThemeContext.Consumer> ); } export default ThemeTogglerButton;
运行结果: