http://codingthesmartway.com/learn-redux-introduction-to-state-management-with-react/
https://github.com/seeschweiler/redux-voting/tree/master/src
//
在React中,共享状态是通过将其移动到需要它的组件的最接近的共同祖先来实现的。这被称为“提升状态”。
https://facebook.github.io/react/docs/lifting-state-up.html#lifting-state-up
https://facebook.github.io/react/docs/components-and-props.html#props-are-read-only
In React, this is usually solved by making a component "controlled".
https://facebook.github.io/react/docs/state-and-lifecycle.html#the-data-flows-down
Neither parent nor child components can know if a certain component is stateful or stateless,
and they shouldn't care whether it is defined as a function or a class.
父组件和子组件都不能知道某个组件是有状态还是无状态,
并且它们不应该关心它是否被定义为一个函数或一个类。
// props is an object!
// message.text => array of objects
class MessageList extends React.Component {
getChildren = () => {
//
}
render() {
const children = this.props.messages.map(
(message, index) => {
return(
<Message
key={index}
text={message.text}
color={message.color}
xyzClick={this.props.xyzClick}
/>
);
}
);
return(
<div>
children = {children}
<hr />
<div>
BAD: <br />
{/* this.props = {this.props} */}
this.props.children = {this.props.color}
{/* this.props.arr = {this.props.arr} */}
{/* this.props.obj = {this.props.obj} */}
</div>
</div>
);
}
}
// text={message.text} => message object
class Message extends React.Component {
test(){
console.log(this.props.key);
}
render() {
return (
<div>
this.props.text = {this.props.text}
<br />
this.props.color = <span style={{backgroundColor: this.props.color}}>{this.props.color}</span>
<br />
this.props.key = {this.props.key}
<br />
<Button color={this.props.color} xyzClick={this.props.xyzClick}>Delete</Button>
</div>
);
}
}
// props.children ???
class Button extends React.Component {
render() {
return (
<button
style={{background: this.props.color}}
onClick={(e) => this.props.xyzClick(e)} >
{this.props.children}
</button>
);
}
}
const text = [
{
text: "text 1",
color: "red"
},
{
text: "text 2",
color: "blue"
},
{
text: "text 3",
color: "gery"
},
{
text: "text 4",
color: "green"
},
{
text: "text 5",
color: "#f0f"
}
];
const color = "green";
const ArrayTest = [1, 2, 3];
const ObjectTest = {"key": "value"};
class App extends React.Component{
XC = (e) => {
let m = e.toString();
console.log(e, m);
return alert(`e.toString(); =\n`, m);
};
render(){
return(
<div>
<MessageList
messages={text}
color={color}
arr={ArrayTest}
obj={ObjectTest}
xyzClick={this.XC}/>
</div>
);
}
};
export default App;
ReactDOM.render(
<App />,
mountNode
);
FormItem
= Form.Item;
const FormItem = Form.Item;
https://react2.xgqfrms.xyz/docs/jsx-in-depth.html#命名组件namespaced-components
只需要把你的"子组件"创建为主组件的属性。
Class Properties
& bind(this)
https://facebook.github.io/react/docs/react-without-es6.html
https://react2.xgqfrms.xyz/docs/jsx-in-depth.html#注释
var content = (
<Nav>
{/* child comment, 用 {} 包围 */}
<Person
/* 多
行
注释 */
name={window.isLoggedIn ? window.name : ''} // 行尾注释
/>
</Nav>
);
https://github.com/dvajs/dva-knowledgemap#往下传数据
父组件通过 props 传递 state 到子组件
https://github.com/dvajs/dva-knowledgemap#往上传数据
子组件通过调用父组件的 props 传递来的方法来修改 state
https://facebook.github.io/react/docs/composition-vs-inheritance.html
请记住,组件可以接受任意
props
,包括原始值,React元素或函数。
Remember that components may accept arbitrary props, including primitive values, React elements, or functions.
import React, {Component} from 'react';
const FancyBorder = (props) => {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
const Dialog = (props) => {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
{props.children}
</FancyBorder>
);
}
class SignUpDialog extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.state = {
login: ''
};
}
handleChange(e) {
this.setState({
login: e.target.value
});
}
handleSignUp() {
alert(`Welcome aboard, ${this.state.login}!`);
}
render(props) {
const record = this.props.data;
console.log(`this.props.data`, this.props.data);
return (
<div>
<Dialog
title="Mars Exploration Program"
message="How should we refer to you?"
>
<input
value={this.state.login}
onChange={this.handleChange}
/>
<button
onClick={this.handleSignUp}
>
Sign Me Up!
</button>
</Dialog>
</div>
);
}
}
export {SignUpDialog};
export default SignUpDialog;
https://ant.design/components/form-cn/#components-form-demo-validate-other
import React, {Component} from 'react';
import {Form, Icon, Input, Button} from 'antd';
import {DatePicker, TimePicker} from 'antd';
const {MonthPicker, RangePicker} = DatePicker;
// import moment from 'moment';
const FormItem = Form.Item;
const hasErrors = (fieldsError) => {
// 测试数组中的某些元素是否通过由提供的函数实现的测试。
return Object.keys(fieldsError).some(field => fieldsError[field]);
};
const today = new Date().toLocaleString();
class HLF extends Component {
constructor(props) {
super(props);
// this.onChange = this.onChange.bind(this);
// this.onStartChange = this.onStartChange.bind(this);
}
state = {
startValue: today
};
onChange = (field, value) => {
this.setState({
[field]: value,
});
};
onStartChange = (value) => {
console.log('typeof DatePicker value = \n', typeof(value));
console.log('DatePicker value = \n', value);
// value = value._d;
this.onChange('startValue', value);
console.log('DatePicker new value = \n', value);
};
componentDidMount() {
// To disabled submit button at the beginning.
this.props.form.validateFields();
}
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
clickSearchHandler = (e) => {
e.preventDefault();
console.log('Received values of form: ', e);
let event = e;
alert(event);
};
render() {
// 解构赋值
// alert(this.props.form);
console.log(`this.props.form`, this.props.form);
const {getFieldDecorator, getFieldsError, getFieldError, isFieldTouched} = this.props.form;
// Only show error after a field is touched.
const userNameError = isFieldTouched('userName') && getFieldError('userName');
const textError = isFieldTouched('text') && getFieldError('text');
const userTypeError = isFieldTouched('text') && getFieldError('text');
//
const phoneTypeError = isFieldTouched('text') && getFieldError('text');
const emailTypeError = isFieldTouched('email') && getFieldError('email');
return (
<Form layout="inline" onSubmit={this.handleSubmit}>
<FormItem
validateStatus={userNameError ? 'error' : ''}
help={userNameError || ''}
label="登录名"
>
{
getFieldDecorator('userName', {
rules: [{ required: false, message: '登录名' }],
})
(
<Input prefix={<Icon type="user" style={{ fontSize: 13 }} />} placeholder="登录名" />
)
}
</FormItem>
<FormItem
validateStatus={textError ? 'error' : ''}
help={textError || ''}
label="用户ID"
style={{}}
>
{
getFieldDecorator('text', {
rules: [{ required: false, message: '用户ID' }],
})
(
<Input prefix={<Icon type="idcard" style={{ fontSize: 13 }} />} type="text" placeholder="用户ID" />
)
}
</FormItem>
<FormItem
validateStatus={userTypeError ? 'error' : ''}
help={userTypeError || ''}
label="用户类型"
>
{
getFieldDecorator('text', {
rules: [{ required: false, message: '用户类型!' }],
})
(
<Input prefix={<Icon type="contacts" style={{ fontSize: 13 }} />} placeholder="用户类型" />
)
}
</FormItem>
<FormItem
validateStatus={textError ? 'error' : ''}
help={textError || ''}
label="用户姓名"
style={{}}
>
{
getFieldDecorator('text', {
rules: [{ required: false, message: '用户姓名' }],
})
(
<Input prefix={<Icon type="user-add" style={{ fontSize: 13 }} />} type="text" placeholder="用户姓名" />
)
}
</FormItem>
<br/>
<FormItem
validateStatus={phoneTypeError ? 'error' : ''}
help={phoneTypeError || ''}
label="手机号"
style={{}}
>
{
getFieldDecorator('number', {
rules: [{ required: false, message: '手机号' }],
})
(
<Input prefix={<Icon type="phone" style={{ fontSize: 13 }} />} type="number" placeholder="手机号" />
)
}
</FormItem>
<FormItem
validateStatus={emailTypeError ? 'error' : ''}
help={emailTypeError || ''}
label={<span className="left-spaces">邮箱</span>}
style={{}}
>
{
getFieldDecorator('email', {
rules: [{ required: false, message: '邮箱' }],
})
(
<Input prefix={<Icon type="mail" style={{ fontSize: 13 }} />} type="email" placeholder="邮箱" />
)
}
</FormItem>
<FormItem
validateStatus={textError ? 'error' : ''}
help={textError || ''}
label="激活状态"
style={{}}
>
{
getFieldDecorator('text', {
rules: [{ required: false, message: '激活状态' }],
})
(
<Input prefix={<Icon type="file-text" style={{ fontSize: 13 }} />} type="text" placeholder="激活状态" />
)
}
</FormItem>
<FormItem
validateStatus={textError ? 'error' : ''}
help={textError || ''}
label="有效日期"
style={{}}
>
{
getFieldDecorator('text', {
rules: [{ required: false, message: '有效日期' }],
})
(
<div>
<RangePicker
showTime
format="YYYY-MM-DD HH:mm:ss"
onChange={(e) => this.onStartChange(e)}
/>
</div>
)
}
</FormItem>
<span className="search-spaces"/>
<FormItem>
<Button
icon="search"
type="primary"
htmlType="submit"
id="user-check-search"
onClick={this.clickSearchHandler}
>
查询
</Button>
</FormItem>
</Form>
);
}
}
const WHLF = Form.create({})(HLF);
export {WHLF};
export default WHLF;
/*
用户ID
用户姓名
登录名
手机号
邮箱
激活状态
有效日期
用户类型: 内部用户
*/
https://gist.github.com/xgqfrms-GitHub/4cf5cc3a67a9ed094cf008f13457bfac
直接编辑 Table
https://github.com/ant-design/ant-design/blob/design-pattern/docs/pattern/table/demo/edit-directly.md
https://lodash.com/docs#debounce