学习React官方文档(二)

133 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天

文接上回,这几天一直在熟悉公司的代码

条件渲染

使用if运算符或条件运算符去创建元素当前的状态,然后React根据状态更新UI

如下面这两个组件

function UserGreeting(props) {
	return <h1>Welcom back! </h1>;
}

funtion GuesGreeting(props) {
	return <h1>Please sign up </h1>;
}

在创建一个Greeeting组件,他将会根据用户是否登陆决定显示哪一个组件

function Greeting(props) {
	const isLoggedIn = props.isLoggedIn;
	if(isLoggedIn) {
		return <UserGreeting />;
	}
	return <GuestGreeting />;
}

ReactDOM.render(
	<Greeting isLoggedIn={false} />
	document.getElementById('root')
);

以上这个Grrrting组件将根据isLoggedIn的值显示那个组件。

阻止组件渲染

class Page extends React.component {
	constructor(props) {
		super(props);
		this.state = {showWarning: true};
}

handleToggleClick = () => {
	this.state(state => ({
			showWarning: !state.showWarning
	}));
}

function WarningBanner(props) {
		if(!props.warn) {
		return null;
}
 return (
	 <div className = 'warning'>
		 Warning!
	 </div>
 );
}

render() {
	return (
		<div> 
			<WarningBanner warn={this.state.showWarning} />
			<button onClick={this.handleToggleClick}>
				{this.state.showWarning ? 'Hide' : 'Show' }
		<div>
	);
	}
}

ReactDOM.render(
		<Page />
		document.getElementById('root')
);

列表&Key

基础列表组件

function NumberList(props) {
	const numbers = props.numbers;
	const listItems = numbers.map((number) => 
		<li>{number}</li>
);
	return (
		<ul>{lidtItems}</ul>
	);
}

const numbers = [1, 2, 3, 4, 5];
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<NumberList numbers={numbers} />);

以上这段代码在运行时会提示警告,a key should be provied for list items

意思是当你创建一个元素时,必须包含一个特殊的key属性。下面,让我们给每个列表分配一个key属性来解决这个警告

function NumberList(props) {
	const numbers = props.numbers;
	const listItems = numbers.map((number) => 
		<li key={number.toString()}>
			{number}
		</li>
	);
	return (
		<ul>{listItems}</ul>
	);
}

Key

key的作用是帮助React识别哪些元素改变了,比如添加或删除。因此你应该给数组中的每一个元素赋予一个确定的标识。

const numbers = [1, 2, 3, 4];
const listItems = number.map((number) =>
	<li> key={number.toString()>
		{number}
	</li>
};

一个元素的key最好是这个元素独一无二的字符串, 通常我们使用数据中的id作为元素的key

如下所示:

const todoItems = todos.map((todo) => 
	<li key={todo.key}>
		{todo.text}
	</li>
	);

当元素没有确定id的时候,万不得已你可以使用元素索引index作为key

const todoItems = todos.map((todo, index) => 
	<li key={index}>
		{todo.text}
	</li>
);

如果列表项目的顺序可能会发生变化,不建议使用索引来用作key值,因为这样会导致性能变差,还可能引起组件状态的问题。

用key提取组件

元素的key只有放在就近的上下文中才有意义。

比如说,你提取一个ListItem组件,应该把key保留在数组中的元素上,而不是放在ListItem组件中的

  • 元素上,正确的组件使用方法如下

    function ListItem(props) {
    	return <li>{props.value}</li>;
    }
    
    function NumberList(props) {
    	const number = props.numbers;
    	const listItems = numbers.map((number) =>
    		<ListItem key={number.toString()} value={number} />
    	);
    	return (
    		<ul>
    			{listItems}
    		</ul>
    	);
    }
    

    Key值在兄弟节点之间必须唯一

    数组元素中使用的key值在其兄弟节点之间应该是独一无二的,然而,他们不需要是全局唯一的,当我们生成两个不同的数组时,可以使用相同的key值

    function Blog(props) {
      const sidebar = (
        <ul>
          {props.posts.map((post) =>
            <li key={post.id}>
              {post.title}
            </li>
          )}
        </ul>
      );
      const content = props.posts.map((post) =>
        <div key={post.id}>
          <h3>{post.title}</h3>
          <p>{post.content}</p>
        </div>
      );
      return (
        <div>
          {sidebar}
          <hr />
          {content}
        </div>
      );
    }
    
    const posts = [
      {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
      {id: 2, title: 'Installation', content: 'You can install React from npm.'}
    ];
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<Blog posts={posts} />);
    

    key值会传递信息给React,但不会传递信息给组件。当组件中需要使用key的属性值时,可以用其他属性名显式传递这个值

    const content = posts.map((post) =>
    	<Post 
    		key={post.id}
    		id={post.id}
    		title={post.title} />
    );
    

    上述代码,Post组件可以读出props.id,但是不能读出props.key

    表单

    在React中,可变状态通常保存在组件的state属性中,并且只能通过setState()来更新。

    class NameForm extends React.Component {
    	constructor(props) {
    		super(props);
    		this.state = {value: ''};
    		
    		this.handleChange = this.handleChange.bind(this);
    		this.handleSubmit = this.handleSubmit.bind(this);
    }
    
    handleChange(event) {
    	this.setState({value: event.target.value});
    }
    
    handleSubmit(event) {
    	alert('提交的名字:' + this.state.value);
    	event.preventDefault();
    }
    
    render() {
    	return (
    		<form onSubmit={this.handleSubmit}>
    			<label>
    				名字:
    				<input type="text" value={this.state.value} onChange={this.handleChange} />
    			</label>
    			<input type="submit" value="提交" />
        </form>
    	  );
      }
    }
    

    在表单上设置了value属性,所以显示的值始终将为this.state.value,就使得React的state成为唯一的数据源。当handleChange执行后,更新相应的state,因此显示的值也进行更新

    状态提升

    下面这个示例中,创建一个用于计算水在给定的温度下是否会沸腾的温度计算器

    const scaleName = {
    	c: 'Celsius',
    	f: 'Fahrenheit'
    };
    
    function toCelsius(fahrenheit) {
    	return (fahrenheit -32) * 5 / 9;
    }
    
    function toFahrenheit(celsius) {
    	return (celsius * 9 /5) + 32;
    }
    
    function tryConvert(temperature, convert) {
    	const input = parserFloat(temperature;
    	if(Number.isNaN(input)) {
    		return '';
    	}
    	const output = convert(input);
    	const rounded = Math.round(output *1000) / 1000;
    	return rounded.toString();
    }
    
    function BoilingVerdict(props) {
    	if(props.celsius >=100) {
    		return <p>The water would boil <p>
    	}
    	return <p>The water would not boil </p>;
    }
    
    class TemperatureInput extends React.Component {
    	constructor(props) {
    		super(props);
    		this.handleChange = this.handleChange.binf(this);
    	}
    
    handleChange(e) {
    	this.props.onTemperatureChange(e.target.value);
    }
    
    render() {
    	const temperature = this.props.temperature;
    	const scale = this.props.scale;
    	return(
    		<filedest>
    			<legend>Enter temperature in {scaleNames[scale]}</legend>
    			<input value={temperature}
    							onChange={this.handleChange} />
    		<fieldest>
    	);
    }
    }
    

    现在我们有了两个输入框,但是当你在其中一个输入温度时,另外一个输入框并不会更新。

    在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”