From 659cef8a98065dc2bdca7869a6cbfb53e9a0a49a Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 21 Oct 2016 21:37:29 +0100 Subject: [PATCH] Rebuild website manually --- 404.html | 106 +- acknowledgements.html | 106 +- blog/2013/06/02/jsfiddle-integration.html | 172 ++- blog/2013/06/05/why-react.html | 173 ++- blog/2013/06/12/community-roundup.html | 172 ++- blog/2013/06/19/community-roundup-2.html | 172 ++- blog/2013/06/21/react-v0-3-3.html | 172 ++- blog/2013/06/27/community-roundup-3.html | 172 ++- .../07/02/react-v0-4-autobind-by-default.html | 172 ++- blog/2013/07/03/community-roundup-4.html | 174 ++- ...-4-prop-validation-and-default-values.html | 172 ++- blog/2013/07/17/react-v0-4-0.html | 172 ++- blog/2013/07/23/community-roundup-5.html | 176 ++- blog/2013/07/26/react-v0-4-1.html | 172 ++- .../use-react-and-jsx-in-ruby-on-rails.html | 172 ++- blog/2013/08/05/community-roundup-6.html | 172 ++- ...-react-and-jsx-in-python-applications.html | 172 ++- blog/2013/08/26/community-roundup-7.html | 172 ++- blog/2013/09/24/community-roundup-8.html | 172 ++- blog/2013/10/03/community-roundup-9.html | 174 ++- blog/2013/10/16/react-v0.5.0.html | 172 ++- blog/2013/10/29/react-v0-5-1.html | 172 ++- blog/2013/11/05/thinking-in-react.html | 8 +- blog/2013/11/06/community-roundup-10.html | 174 ++- blog/2013/11/18/community-roundup-11.html | 176 ++- blog/2013/12/18/react-v0.5.2-v0.4.2.html | 172 ++- blog/2013/12/19/react-v0.8.0.html | 172 ++- blog/2013/12/23/community-roundup-12.html | 172 ++- blog/2013/12/30/community-roundup-13.html | 176 ++- .../01/02/react-chrome-developer-tools.html | 198 +-- blog/2014/01/06/community-roundup-14.html | 174 ++- blog/2014/02/05/community-roundup-15.html | 174 ++- blog/2014/02/15/community-roundup-16.html | 174 ++- blog/2014/02/16/react-v0.9-rc1.html | 172 ++- blog/2014/02/20/react-v0.9.html | 172 ++- blog/2014/02/24/community-roundup-17.html | 174 ++- blog/2014/03/14/community-roundup-18.html | 174 ++- blog/2014/03/19/react-v0.10-rc1.html | 172 ++- blog/2014/03/21/react-v0.10.html | 172 ++- blog/2014/03/28/the-road-to-1.0.html | 172 ++- blog/2014/04/04/reactnet.html | 175 ++- blog/2014/05/06/flux.html | 174 ++- .../05/29/one-year-of-open-source-react.html | 172 ++- blog/2014/06/27/community-roundup-19.html | 175 ++- blog/2014/07/13/react-v0.11-rc1.html | 172 ++- blog/2014/07/17/react-v0.11.html | 172 ++- blog/2014/07/25/react-v0.11.1.html | 172 ++- blog/2014/07/28/community-roundup-20.html | 178 ++- .../30/flux-actions-and-the-dispatcher.html | 172 ++- blog/2014/08/03/community-roundup-21.html | 175 ++- .../03/introducing-the-jsx-specification.html | 172 ++- blog/2014/09/12/community-round-up-22.html | 176 ++- blog/2014/09/16/react-v0.11.2.html | 172 ++- .../2014/09/24/testing-flux-applications.html | 172 ++- .../10/14/introducing-react-elements.html | 172 ++- blog/2014/10/16/react-v0.12-rc1.html | 172 ++- blog/2014/10/17/community-roundup-23.html | 178 ++- blog/2014/10/27/react-js-conf.html | 172 ++- blog/2014/10/28/react-v0.12.html | 172 ++- blog/2014/11/24/react-js-conf-updates.html | 174 ++- blog/2014/11/25/community-roundup-24.html | 179 ++- blog/2014/12/18/react-v0.12.2.html | 172 ++- .../react-js-conf-diversity-scholarship.html | 172 ++- blog/2015/01/27/react-v0.13.0-beta-1.html | 172 ++- blog/2015/02/18/react-conf-roundup-2015.html | 214 +-- .../02/20/introducing-relay-and-graphql.html | 173 ++- blog/2015/02/24/react-v0.13-rc1.html | 172 ++- .../02/24/streamlining-react-elements.html | 172 ++- blog/2015/03/03/react-v0.13-rc2.html | 172 ++- blog/2015/03/04/community-roundup-25.html | 175 ++- blog/2015/03/10/react-v0.13.html | 172 ++- blog/2015/03/16/react-v0.13.1.html | 172 ++- ...ing-the-facebook-news-feed-with-relay.html | 172 ++- blog/2015/03/26/introducing-react-native.html | 172 ++- blog/2015/03/30/community-roundup-26.html | 174 ++- blog/2015/04/17/react-native-v0.4.html | 172 ++- blog/2015/04/18/react-v0.13.2.html | 172 ++- blog/2015/05/01/graphql-introduction.html | 172 ++- blog/2015/05/08/react-v0.13.3.html | 172 ++- .../05/22/react-native-release-process.html | 174 ++- ...precating-jstransform-and-react-tools.html | 172 ++- blog/2015/07/03/react-v0.14-beta-1.html | 172 ++- blog/2015/08/03/new-react-devtools-beta.html | 173 ++- blog/2015/08/11/relay-technical-preview.html | 171 ++- blog/2015/08/13/reacteurope-roundup.html | 290 ++-- .../2015/09/02/new-react-developer-tools.html | 172 ++- blog/2015/09/10/react-v0.14-rc1.html | 172 ++- blog/2015/09/14/community-roundup-27.html | 172 ++- .../10/01/react-render-and-top-level-api.html | 172 ++- blog/2015/10/07/react-v0.14.html | 172 ++- .../19/reactiflux-is-moving-to-discord.html | 172 ++- blog/2015/10/28/react-v0.14.1.html | 172 ++- blog/2015/11/02/react-v0.14.2.html | 172 ++- blog/2015/11/18/react-v0.14.3.html | 172 ++- ...ct-js-conf-2016-diversity-scholarship.html | 172 ++- blog/2015/12/16/ismounted-antipattern.html | 172 ++- ...act-components-elements-and-instances.html | 172 ++- blog/2015/12/29/react-v0.14.4.html | 172 ++- ...-implies-B-does-not-imply-B-implies-A.html | 172 ++- .../2016/01/12/discontinuing-ie8-support.html | 172 ++- blog/2016/02/19/new-versioning-scheme.html | 172 ++- blog/2016/03/07/react-v15-rc1.html | 172 ++- blog/2016/03/16/react-v15-rc2.html | 172 ++- blog/2016/03/29/react-v0.14.8.html | 172 ++- blog/2016/04/07/react-v15.html | 172 ++- blog/2016/04/08/react-v15.0.1.html | 172 ++- .../introducing-reacts-error-code-system.html | 172 ++- .../2016/07/13/mixins-considered-harmful.html | 172 ++- .../22/create-apps-with-no-configuration.html | 172 ++- blog/2016/08/05/relay-state-of-the-state.html | 172 ++- blog/2016/09/28/our-first-50000-stars.html | 172 ++- blog/all.html | 106 +- blog/index.html | 106 +- blog/page10/index.html | 150 ++- blog/page11/index.html | 120 +- blog/page12/index.html | 110 +- blog/page13/index.html | 114 +- blog/page14/index.html | 110 +- blog/page15/index.html | 108 +- blog/page16/index.html | 112 +- blog/page17/index.html | 114 +- blog/page18/index.html | 112 +- blog/page19/index.html | 108 +- blog/page2/index.html | 106 +- blog/page20/index.html | 110 +- blog/page21/index.html | 108 +- blog/page22/index.html | 106 +- blog/page3/index.html | 106 +- blog/page4/index.html | 106 +- blog/page5/index.html | 106 +- blog/page6/index.html | 124 +- blog/page7/index.html | 108 +- blog/page8/index.html | 108 +- blog/page9/index.html | 110 +- community/conferences.html | 243 ++++ community/support.html | 214 +++ community/videos.html | 341 +++++ contributing/codebase-overview.html | 733 +++++----- contributing/design-principles.html | 711 +++++----- contributing/how-to-contribute.html | 713 +++++----- contributing/implementation-notes.html | 711 +++++----- css/react.css | 2 +- docs/addons-it-IT.html | 519 -------- docs/addons-ja-JP.html | 515 -------- docs/addons-ko-KR.html | 517 -------- docs/addons-zh-CN.html | 518 -------- docs/addons.html | 531 ++++---- docs/advanced-performance-it-IT.html | 651 --------- docs/advanced-performance-ja-JP.html | 649 --------- docs/advanced-performance-ko-KR.html | 651 --------- docs/advanced-performance-zh-CN.html | 654 --------- docs/advanced-performance.html | 661 +-------- docs/animation-it-IT.html | 703 ---------- docs/animation-ja-JP.html | 674 ---------- docs/animation-ko-KR.html | 697 ---------- docs/animation-zh-CN.html | 697 ---------- docs/animation.html | 902 ++++++------- docs/class-name-manipulation-it-IT.html | 545 -------- docs/class-name-manipulation-ja-JP.html | 544 -------- docs/class-name-manipulation-ko-KR.html | 545 -------- docs/class-name-manipulation-zh-CN.html | 503 ------- docs/class-name-manipulation.html | 503 ------- docs/clone-with-props-it-IT.html | 523 -------- docs/clone-with-props-ja-JP.html | 523 -------- docs/clone-with-props-ko-KR.html | 525 -------- docs/clone-with-props-zh-CN.html | 525 -------- docs/clone-with-props.html | 525 -------- docs/component-api-it-IT.html | 560 -------- docs/component-api-ko-KR.html | 560 -------- docs/component-api-zh-CN.html | 560 -------- docs/component-api.html | 560 -------- docs/component-specs-it-IT.html | 623 --------- docs/component-specs-ko-KR.html | 624 --------- docs/component-specs-zh-CN.html | 625 --------- docs/component-specs.html | 625 --------- docs/components-and-props.html | 606 +++++++++ docs/composition-vs-inheritance.html | 544 ++++++++ docs/conditional-rendering.html | 603 +++++++++ docs/conferences-it-IT.html | 517 ++------ docs/conferences-ko-KR.html | 517 ++------ docs/conferences-zh-CN.html | 519 ++------ docs/conferences.html | 546 +------- docs/context-ko-KR.html | 634 --------- docs/context-zh-CN.html | 661 --------- docs/context.html | 791 +++++------ docs/create-fragment-it-IT.html | 554 -------- docs/create-fragment-ja-JP.html | 553 -------- docs/create-fragment-ko-KR.html | 556 -------- docs/create-fragment-zh-CN.html | 556 -------- docs/create-fragment.html | 724 +++++----- docs/displaying-data-it-IT.html | 591 --------- docs/displaying-data-ja-JP.html | 591 --------- docs/displaying-data-ko-KR.html | 591 --------- docs/displaying-data-ru-RU.html | 591 --------- docs/displaying-data-zh-CN.html | 591 --------- docs/displaying-data-zh-TW.html | 592 --------- docs/displaying-data.html | 599 +-------- docs/dom-differences-it-IT.html | 507 ------- docs/dom-differences-ko-KR.html | 518 -------- docs/dom-differences-zh-CN.html | 508 ------- docs/dom-differences.html | 508 ------- docs/dom-elements.html | 516 ++++++++ docs/environments.html | 567 +------- docs/error-decoder.html | 493 +++---- docs/events-it-IT.html | 650 --------- docs/events-ko-KR.html | 652 --------- docs/events-zh-CN.html | 668 ---------- docs/events.html | 877 ++++++------ docs/flux-overview-it-IT.html | 495 ------- docs/flux-overview-ko-KR.html | 495 ------- docs/flux-overview-zh-CN.html | 495 ------- docs/flux-overview.html | 495 ------- docs/flux-todo-list-it-IT.html | 495 ------- docs/flux-todo-list-ko-KR.html | 495 ------- docs/flux-todo-list-zh-CN.html | 495 ------- docs/flux-todo-list.html | 495 ------- docs/forms-it-IT.html | 611 --------- docs/forms-ja-JP.html | 601 --------- docs/forms-ko-KR.html | 611 --------- docs/forms-zh-CN.html | 620 --------- docs/forms.html | 1056 ++++++++------- docs/getting-started-it-IT.html | 579 -------- docs/getting-started-ja-JP.html | 577 -------- docs/getting-started-ko-KR.html | 606 --------- docs/getting-started-zh-CN.html | 617 --------- docs/getting-started.html | 555 -------- docs/glossary-it-IT.html | 618 --------- docs/glossary-ko-KR.html | 618 --------- docs/glossary-zh-CN.html | 618 --------- docs/glossary.html | 628 +-------- docs/handling-events.html | 515 ++++++++ docs/hello-world.html | 418 ++++++ docs/index-ja-JP.html | 10 - docs/index-ko-KR.html | 10 - docs/index-zh-CN.html | 10 - docs/index.html | 10 - docs/installation.html | 442 +++++++ docs/interactivity-and-dynamic-uis-it-IT.html | 550 -------- docs/interactivity-and-dynamic-uis-ja-JP.html | 552 -------- docs/interactivity-and-dynamic-uis-ko-KR.html | 552 -------- docs/interactivity-and-dynamic-uis-ru-RU.html | 551 -------- docs/interactivity-and-dynamic-uis-zh-CN.html | 550 -------- docs/interactivity-and-dynamic-uis.html | 560 +------- docs/introducing-jsx.html | 515 ++++++++ docs/jsx-gotchas-it-IT.html | 531 -------- docs/jsx-gotchas-ja-JP.html | 530 -------- docs/jsx-gotchas-ko-KR.html | 531 -------- docs/jsx-gotchas-zh-CN.html | 534 -------- docs/jsx-gotchas.html | 534 -------- docs/jsx-in-depth-it-IT.html | 669 ---------- docs/jsx-in-depth-ja-JP.html | 658 --------- docs/jsx-in-depth-ko-KR.html | 664 ---------- docs/jsx-in-depth-zh-CN.html | 663 ---------- docs/jsx-in-depth.html | 875 ++++++------ docs/jsx-spread-it-IT.html | 524 -------- docs/jsx-spread-ja-JP.html | 524 -------- docs/jsx-spread-ko-KR.html | 524 -------- docs/jsx-spread-zh-CN.html | 524 -------- docs/jsx-spread.html | 524 -------- docs/language-tooling.html | 549 -------- docs/lifting-state-up.html | 604 +++++++++ docs/lists-and-keys.html | 640 +++++++++ docs/more-about-refs-it-IT.html | 603 --------- docs/more-about-refs-ja-JP.html | 616 --------- docs/more-about-refs-ko-KR.html | 603 --------- docs/more-about-refs-zh-CN.html | 603 --------- docs/more-about-refs.html | 611 --------- docs/multiple-components-it-IT.html | 636 --------- docs/multiple-components-ja-JP.html | 636 --------- docs/multiple-components-ko-KR.html | 636 --------- docs/multiple-components-zh-CN.html | 636 --------- docs/multiple-components.html | 641 +-------- docs/optimizing-performance.html | 578 ++++++++ docs/package-management.html | 579 -------- docs/perf-it-IT.html | 552 -------- docs/perf-ja-JP.html | 551 -------- docs/perf-ko-KR.html | 552 -------- docs/perf-zh-CN.html | 552 -------- docs/perf.html | 616 ++++----- docs/pure-render-mixin-it-IT.html | 519 -------- docs/pure-render-mixin-ja-JP.html | 517 -------- docs/pure-render-mixin-ko-KR.html | 519 -------- docs/pure-render-mixin-zh-CN.html | 532 -------- docs/pure-render-mixin.html | 723 +++++----- docs/react-api.html | 658 +++++++++ docs/react-component.html | 643 +++++++++ docs/react-dom-server.html | 419 ++++++ docs/react-dom.html | 461 +++++++ docs/react-without-es6.html | 578 ++++++++ docs/react-without-jsx.html | 436 ++++++ docs/reconciliation-it-IT.html | 578 -------- docs/reconciliation-ko-KR.html | 578 -------- docs/reconciliation.html | 672 +++++----- docs/reference-ja-JP.html | 10 - docs/reference-ko-KR.html | 10 - docs/reference-zh-CN.html | 10 - docs/reference.html | 10 - docs/refs-and-the-dom.html | 468 +++++++ docs/rendering-elements.html | 475 +++++++ docs/reusable-components-it-IT.html | 705 ---------- docs/reusable-components-ja-JP.html | 683 ---------- docs/reusable-components-ko-KR.html | 703 ---------- docs/reusable-components-zh-CN.html | 723 ---------- docs/reusable-components.html | 882 ------------- docs/shallow-compare-zh-CN.html | 519 -------- docs/shallow-compare.html | 530 +++----- docs/special-non-dom-attributes-it-IT.html | 505 ------- docs/special-non-dom-attributes-ko-KR.html | 505 ------- docs/special-non-dom-attributes-zh-CN.html | 505 ------- docs/special-non-dom-attributes.html | 505 ------- docs/state-and-lifecycle.html | 762 +++++++++++ docs/tags-and-attributes-it-IT.html | 587 -------- docs/tags-and-attributes-ko-KR.html | 587 -------- docs/tags-and-attributes-zh-CN.html | 591 --------- docs/tags-and-attributes.html | 595 --------- docs/test-utils-it-IT.html | 624 --------- docs/test-utils-ja-JP.html | 577 -------- docs/test-utils-ko-KR.html | 628 --------- docs/test-utils-zh-CN.html | 635 --------- docs/test-utils.html | 840 ++++++------ docs/thinking-in-react-it-IT.html | 638 --------- docs/thinking-in-react-ja-JP.html | 638 --------- docs/thinking-in-react-ko-KR.html | 638 --------- docs/thinking-in-react-zh-CN.html | 638 --------- docs/thinking-in-react.html | 765 +++++------ docs/tooling-integration-it-IT.html | 546 -------- docs/tooling-integration-ja-JP.html | 518 -------- docs/tooling-integration-ko-KR.html | 550 -------- docs/tooling-integration-zh-CN.html | 505 ------- docs/tooling-integration.html | 505 ------- docs/top-level-api-it-IT.html | 592 --------- docs/top-level-api-ja-JP.html | 579 -------- docs/top-level-api-ko-KR.html | 596 --------- docs/top-level-api-zh-CN.html | 600 --------- docs/top-level-api.html | 611 --------- docs/transferring-props-it-IT.html | 614 --------- docs/transferring-props-ja-JP.html | 610 --------- docs/transferring-props-ko-KR.html | 616 --------- docs/transferring-props-zh-CN.html | 614 --------- docs/transferring-props.html | 614 --------- docs/tutorial-it-IT.html | 1100 --------------- docs/tutorial-ja-JP.html | 1176 ----------------- docs/tutorial-ko-KR.html | 1102 --------------- docs/tutorial-zh-CN.html | 1165 ---------------- docs/tutorial.html | 1167 ---------------- docs/two-way-binding-helpers-it-IT.html | 587 -------- docs/two-way-binding-helpers-ja-JP.html | 584 -------- docs/two-way-binding-helpers-ko-KR.html | 591 --------- docs/two-way-binding-helpers-zh-CN.html | 591 --------- docs/two-way-binding-helpers.html | 671 ++++------ docs/typechecking-with-proptypes.html | 532 ++++++++ docs/update-it-IT.html | 556 -------- docs/update-ja-JP.html | 556 -------- docs/update-ko-KR.html | 558 -------- docs/update-zh-CN.html | 558 -------- docs/update.html | 609 ++++----- docs/videos-it-IT.html | 541 ++------ docs/videos-ko-KR.html | 541 ++------ docs/videos-zh-CN.html | 541 ++------ docs/videos.html | 639 +-------- ...ponents-zh-CN.html => web-components.html} | 558 ++++---- docs/webcomponents.html | 539 +------- docs/why-react-de-DE.html | 507 ------- docs/why-react-it-IT.html | 509 ------- docs/why-react-ja-JP.html | 509 ------- docs/why-react-ko-KR.html | 509 ------- docs/why-react-ru-RU.html | 509 ------- docs/why-react-zh-CN.html | 509 ------- docs/why-react-zh-TW.html | 509 ------- docs/why-react.html | 515 +------- docs/working-with-the-browser-it-IT.html | 582 -------- docs/working-with-the-browser-ja-JP.html | 615 --------- docs/working-with-the-browser-ko-KR.html | 582 -------- docs/working-with-the-browser-zh-CN.html | 544 -------- docs/working-with-the-browser.html | 544 -------- downloads.html | 164 --- downloads/single-file-example.html | 21 + img/docs/granular-dom-updates.gif | Bin 0 -> 127160 bytes img/docs/react-devtools-state.gif | Bin 0 -> 705195 bytes img/logo_small.png | Bin 2834 -> 10715 bytes img/logo_small_2x.png | Bin 6806 -> 29070 bytes img/logo_small_gray.png | Bin 0 -> 5556 bytes img/logo_small_gray_2x.png | Bin 0 -> 9481 bytes img/oss_logo.png | Bin 0 -> 4370 bytes img/tutorial/devtools.png | Bin 0 -> 51403 bytes img/tutorial/tictac-empty.png | Bin 0 -> 11152 bytes img/tutorial/tictac-numbers.png | Bin 0 -> 16791 bytes index.html | 139 +- jsx-compiler.html | 106 +- support.html | 139 +- tips/children-props-type-ko-KR.html | 528 -------- tips/children-props-type.html | 534 +------- tips/children-undefined-ko-KR.html | 510 ------- tips/children-undefined.html | 516 +------- .../communicate-between-components-ko-KR.html | 521 -------- tips/communicate-between-components.html | 527 +------- ...ps-not-triggered-after-mounting-ko-KR.html | 497 ------- ...iveProps-not-triggered-after-mounting.html | 497 ------- tips/controlled-input-null-value-ko-KR.html | 504 ------- tips/controlled-input-null-value.html | 510 +------ tips/dangerously-set-inner-html-ko-KR.html | 505 ------- tips/dangerously-set-inner-html.html | 511 +------ tips/dom-event-listeners-ko-KR.html | 528 -------- tips/dom-event-listeners.html | 528 -------- tips/expose-component-functions-ko-KR.html | 541 -------- tips/expose-component-functions-zh-CN.html | 541 -------- tips/expose-component-functions.html | 541 -------- tips/false-in-jsx-ko-KR.html | 506 ------- tips/false-in-jsx.html | 512 +------ tips/if-else-in-JSX-ko-KR.html | 553 -------- tips/if-else-in-JSX-ru-RU.html | 553 -------- tips/if-else-in-JSX.html | 553 -------- tips/initial-ajax-ko-KR.html | 533 -------- tips/initial-ajax.html | 535 -------- tips/inline-styles-ko-KR.html | 505 ------- tips/inline-styles-ru-RU.html | 505 ------- tips/inline-styles.html | 505 ------- tips/introduction-ja-JP.html | 495 ------- tips/introduction-ko-KR.html | 495 ------- tips/introduction-ru-RU.html | 495 ------- tips/introduction.html | 501 +------ ...aximum-number-of-jsx-root-nodes-ko-KR.html | 497 ------- ...aximum-number-of-jsx-root-nodes-ru-RU.html | 497 ------- tips/maximum-number-of-jsx-root-nodes.html | 497 ------- ...getInitialState-as-anti-pattern-ko-KR.html | 543 -------- ...ps-in-getInitialState-as-anti-pattern.html | 546 -------- tips/references-to-components-ko-KR.html | 495 ------- tips/references-to-components.html | 495 ------- tips/self-closing-tag-ja-JP.html | 501 ------- tips/self-closing-tag-ko-KR.html | 501 ------- tips/self-closing-tag-ru-RU.html | 501 ------- tips/self-closing-tag.html | 501 ------- tips/style-props-value-px-ko-KR.html | 530 -------- tips/style-props-value-px-ru-RU.html | 530 -------- tips/style-props-value-px.html | 530 -------- .../use-react-with-other-libraries-ko-KR.html | 521 -------- tips/use-react-with-other-libraries.html | 527 +------- tutorial/tutorial.html | 644 +++++++++ warnings/dont-call-proptypes.html | 106 +- warnings/legacy-factories.html | 106 +- warnings/refs-must-have-owner.html | 106 +- warnings/special-props.html | 106 +- warnings/unknown-prop.html | 106 +- 443 files changed, 34247 insertions(+), 151434 deletions(-) create mode 100644 community/conferences.html create mode 100644 community/support.html create mode 100644 community/videos.html delete mode 100644 docs/addons-it-IT.html delete mode 100644 docs/addons-ja-JP.html delete mode 100644 docs/addons-ko-KR.html delete mode 100644 docs/addons-zh-CN.html delete mode 100644 docs/advanced-performance-it-IT.html delete mode 100644 docs/advanced-performance-ja-JP.html delete mode 100644 docs/advanced-performance-ko-KR.html delete mode 100644 docs/advanced-performance-zh-CN.html delete mode 100644 docs/animation-it-IT.html delete mode 100644 docs/animation-ja-JP.html delete mode 100644 docs/animation-ko-KR.html delete mode 100644 docs/animation-zh-CN.html delete mode 100644 docs/class-name-manipulation-it-IT.html delete mode 100644 docs/class-name-manipulation-ja-JP.html delete mode 100644 docs/class-name-manipulation-ko-KR.html delete mode 100644 docs/class-name-manipulation-zh-CN.html delete mode 100644 docs/class-name-manipulation.html delete mode 100644 docs/clone-with-props-it-IT.html delete mode 100644 docs/clone-with-props-ja-JP.html delete mode 100644 docs/clone-with-props-ko-KR.html delete mode 100644 docs/clone-with-props-zh-CN.html delete mode 100644 docs/clone-with-props.html delete mode 100644 docs/component-api-it-IT.html delete mode 100644 docs/component-api-ko-KR.html delete mode 100644 docs/component-api-zh-CN.html delete mode 100644 docs/component-api.html delete mode 100644 docs/component-specs-it-IT.html delete mode 100644 docs/component-specs-ko-KR.html delete mode 100644 docs/component-specs-zh-CN.html delete mode 100644 docs/component-specs.html create mode 100644 docs/components-and-props.html create mode 100644 docs/composition-vs-inheritance.html create mode 100644 docs/conditional-rendering.html delete mode 100644 docs/context-ko-KR.html delete mode 100644 docs/context-zh-CN.html delete mode 100644 docs/create-fragment-it-IT.html delete mode 100644 docs/create-fragment-ja-JP.html delete mode 100644 docs/create-fragment-ko-KR.html delete mode 100644 docs/create-fragment-zh-CN.html delete mode 100644 docs/displaying-data-it-IT.html delete mode 100644 docs/displaying-data-ja-JP.html delete mode 100644 docs/displaying-data-ko-KR.html delete mode 100644 docs/displaying-data-ru-RU.html delete mode 100644 docs/displaying-data-zh-CN.html delete mode 100644 docs/displaying-data-zh-TW.html delete mode 100644 docs/dom-differences-it-IT.html delete mode 100644 docs/dom-differences-ko-KR.html delete mode 100644 docs/dom-differences-zh-CN.html delete mode 100644 docs/dom-differences.html create mode 100644 docs/dom-elements.html delete mode 100644 docs/events-it-IT.html delete mode 100644 docs/events-ko-KR.html delete mode 100644 docs/events-zh-CN.html delete mode 100644 docs/flux-overview-it-IT.html delete mode 100644 docs/flux-overview-ko-KR.html delete mode 100644 docs/flux-overview-zh-CN.html delete mode 100644 docs/flux-overview.html delete mode 100644 docs/flux-todo-list-it-IT.html delete mode 100644 docs/flux-todo-list-ko-KR.html delete mode 100644 docs/flux-todo-list-zh-CN.html delete mode 100644 docs/flux-todo-list.html delete mode 100644 docs/forms-it-IT.html delete mode 100644 docs/forms-ja-JP.html delete mode 100644 docs/forms-ko-KR.html delete mode 100644 docs/forms-zh-CN.html delete mode 100644 docs/getting-started-it-IT.html delete mode 100644 docs/getting-started-ja-JP.html delete mode 100644 docs/getting-started-ko-KR.html delete mode 100644 docs/getting-started-zh-CN.html delete mode 100644 docs/getting-started.html delete mode 100644 docs/glossary-it-IT.html delete mode 100644 docs/glossary-ko-KR.html delete mode 100644 docs/glossary-zh-CN.html create mode 100644 docs/handling-events.html create mode 100644 docs/hello-world.html delete mode 100644 docs/index-ja-JP.html delete mode 100644 docs/index-ko-KR.html delete mode 100644 docs/index-zh-CN.html delete mode 100644 docs/index.html create mode 100644 docs/installation.html delete mode 100644 docs/interactivity-and-dynamic-uis-it-IT.html delete mode 100644 docs/interactivity-and-dynamic-uis-ja-JP.html delete mode 100644 docs/interactivity-and-dynamic-uis-ko-KR.html delete mode 100644 docs/interactivity-and-dynamic-uis-ru-RU.html delete mode 100644 docs/interactivity-and-dynamic-uis-zh-CN.html create mode 100644 docs/introducing-jsx.html delete mode 100644 docs/jsx-gotchas-it-IT.html delete mode 100644 docs/jsx-gotchas-ja-JP.html delete mode 100644 docs/jsx-gotchas-ko-KR.html delete mode 100644 docs/jsx-gotchas-zh-CN.html delete mode 100644 docs/jsx-gotchas.html delete mode 100644 docs/jsx-in-depth-it-IT.html delete mode 100644 docs/jsx-in-depth-ja-JP.html delete mode 100644 docs/jsx-in-depth-ko-KR.html delete mode 100644 docs/jsx-in-depth-zh-CN.html delete mode 100644 docs/jsx-spread-it-IT.html delete mode 100644 docs/jsx-spread-ja-JP.html delete mode 100644 docs/jsx-spread-ko-KR.html delete mode 100644 docs/jsx-spread-zh-CN.html delete mode 100644 docs/jsx-spread.html delete mode 100644 docs/language-tooling.html create mode 100644 docs/lifting-state-up.html create mode 100644 docs/lists-and-keys.html delete mode 100644 docs/more-about-refs-it-IT.html delete mode 100644 docs/more-about-refs-ja-JP.html delete mode 100644 docs/more-about-refs-ko-KR.html delete mode 100644 docs/more-about-refs-zh-CN.html delete mode 100644 docs/more-about-refs.html delete mode 100644 docs/multiple-components-it-IT.html delete mode 100644 docs/multiple-components-ja-JP.html delete mode 100644 docs/multiple-components-ko-KR.html delete mode 100644 docs/multiple-components-zh-CN.html create mode 100644 docs/optimizing-performance.html delete mode 100644 docs/package-management.html delete mode 100644 docs/perf-it-IT.html delete mode 100644 docs/perf-ja-JP.html delete mode 100644 docs/perf-ko-KR.html delete mode 100644 docs/perf-zh-CN.html delete mode 100644 docs/pure-render-mixin-it-IT.html delete mode 100644 docs/pure-render-mixin-ja-JP.html delete mode 100644 docs/pure-render-mixin-ko-KR.html delete mode 100644 docs/pure-render-mixin-zh-CN.html create mode 100644 docs/react-api.html create mode 100644 docs/react-component.html create mode 100644 docs/react-dom-server.html create mode 100644 docs/react-dom.html create mode 100644 docs/react-without-es6.html create mode 100644 docs/react-without-jsx.html delete mode 100644 docs/reconciliation-it-IT.html delete mode 100644 docs/reconciliation-ko-KR.html delete mode 100644 docs/reference-ja-JP.html delete mode 100644 docs/reference-ko-KR.html delete mode 100644 docs/reference-zh-CN.html delete mode 100644 docs/reference.html create mode 100644 docs/refs-and-the-dom.html create mode 100644 docs/rendering-elements.html delete mode 100644 docs/reusable-components-it-IT.html delete mode 100644 docs/reusable-components-ja-JP.html delete mode 100644 docs/reusable-components-ko-KR.html delete mode 100644 docs/reusable-components-zh-CN.html delete mode 100644 docs/reusable-components.html delete mode 100644 docs/shallow-compare-zh-CN.html delete mode 100644 docs/special-non-dom-attributes-it-IT.html delete mode 100644 docs/special-non-dom-attributes-ko-KR.html delete mode 100644 docs/special-non-dom-attributes-zh-CN.html delete mode 100644 docs/special-non-dom-attributes.html create mode 100644 docs/state-and-lifecycle.html delete mode 100644 docs/tags-and-attributes-it-IT.html delete mode 100644 docs/tags-and-attributes-ko-KR.html delete mode 100644 docs/tags-and-attributes-zh-CN.html delete mode 100644 docs/tags-and-attributes.html delete mode 100644 docs/test-utils-it-IT.html delete mode 100644 docs/test-utils-ja-JP.html delete mode 100644 docs/test-utils-ko-KR.html delete mode 100644 docs/test-utils-zh-CN.html delete mode 100644 docs/thinking-in-react-it-IT.html delete mode 100644 docs/thinking-in-react-ja-JP.html delete mode 100644 docs/thinking-in-react-ko-KR.html delete mode 100644 docs/thinking-in-react-zh-CN.html delete mode 100644 docs/tooling-integration-it-IT.html delete mode 100644 docs/tooling-integration-ja-JP.html delete mode 100644 docs/tooling-integration-ko-KR.html delete mode 100644 docs/tooling-integration-zh-CN.html delete mode 100644 docs/tooling-integration.html delete mode 100644 docs/top-level-api-it-IT.html delete mode 100644 docs/top-level-api-ja-JP.html delete mode 100644 docs/top-level-api-ko-KR.html delete mode 100644 docs/top-level-api-zh-CN.html delete mode 100644 docs/top-level-api.html delete mode 100644 docs/transferring-props-it-IT.html delete mode 100644 docs/transferring-props-ja-JP.html delete mode 100644 docs/transferring-props-ko-KR.html delete mode 100644 docs/transferring-props-zh-CN.html delete mode 100644 docs/transferring-props.html delete mode 100644 docs/tutorial-it-IT.html delete mode 100644 docs/tutorial-ja-JP.html delete mode 100644 docs/tutorial-ko-KR.html delete mode 100644 docs/tutorial-zh-CN.html delete mode 100644 docs/tutorial.html delete mode 100644 docs/two-way-binding-helpers-it-IT.html delete mode 100644 docs/two-way-binding-helpers-ja-JP.html delete mode 100644 docs/two-way-binding-helpers-ko-KR.html delete mode 100644 docs/two-way-binding-helpers-zh-CN.html create mode 100644 docs/typechecking-with-proptypes.html delete mode 100644 docs/update-it-IT.html delete mode 100644 docs/update-ja-JP.html delete mode 100644 docs/update-ko-KR.html delete mode 100644 docs/update-zh-CN.html rename docs/{webcomponents-zh-CN.html => web-components.html} (50%) delete mode 100644 docs/why-react-de-DE.html delete mode 100644 docs/why-react-it-IT.html delete mode 100644 docs/why-react-ja-JP.html delete mode 100644 docs/why-react-ko-KR.html delete mode 100644 docs/why-react-ru-RU.html delete mode 100644 docs/why-react-zh-CN.html delete mode 100644 docs/why-react-zh-TW.html delete mode 100644 docs/working-with-the-browser-it-IT.html delete mode 100644 docs/working-with-the-browser-ja-JP.html delete mode 100644 docs/working-with-the-browser-ko-KR.html delete mode 100644 docs/working-with-the-browser-zh-CN.html delete mode 100644 docs/working-with-the-browser.html delete mode 100644 downloads.html create mode 100644 downloads/single-file-example.html create mode 100644 img/docs/granular-dom-updates.gif create mode 100644 img/docs/react-devtools-state.gif create mode 100644 img/logo_small_gray.png create mode 100644 img/logo_small_gray_2x.png create mode 100644 img/oss_logo.png create mode 100644 img/tutorial/devtools.png create mode 100644 img/tutorial/tictac-empty.png create mode 100644 img/tutorial/tictac-numbers.png delete mode 100644 tips/children-props-type-ko-KR.html delete mode 100644 tips/children-undefined-ko-KR.html delete mode 100644 tips/communicate-between-components-ko-KR.html delete mode 100644 tips/componentWillReceiveProps-not-triggered-after-mounting-ko-KR.html delete mode 100644 tips/componentWillReceiveProps-not-triggered-after-mounting.html delete mode 100644 tips/controlled-input-null-value-ko-KR.html delete mode 100644 tips/dangerously-set-inner-html-ko-KR.html delete mode 100644 tips/dom-event-listeners-ko-KR.html delete mode 100644 tips/dom-event-listeners.html delete mode 100644 tips/expose-component-functions-ko-KR.html delete mode 100644 tips/expose-component-functions-zh-CN.html delete mode 100644 tips/expose-component-functions.html delete mode 100644 tips/false-in-jsx-ko-KR.html delete mode 100644 tips/if-else-in-JSX-ko-KR.html delete mode 100644 tips/if-else-in-JSX-ru-RU.html delete mode 100644 tips/if-else-in-JSX.html delete mode 100644 tips/initial-ajax-ko-KR.html delete mode 100644 tips/initial-ajax.html delete mode 100644 tips/inline-styles-ko-KR.html delete mode 100644 tips/inline-styles-ru-RU.html delete mode 100644 tips/inline-styles.html delete mode 100644 tips/introduction-ja-JP.html delete mode 100644 tips/introduction-ko-KR.html delete mode 100644 tips/introduction-ru-RU.html delete mode 100644 tips/maximum-number-of-jsx-root-nodes-ko-KR.html delete mode 100644 tips/maximum-number-of-jsx-root-nodes-ru-RU.html delete mode 100644 tips/maximum-number-of-jsx-root-nodes.html delete mode 100644 tips/props-in-getInitialState-as-anti-pattern-ko-KR.html delete mode 100644 tips/props-in-getInitialState-as-anti-pattern.html delete mode 100644 tips/references-to-components-ko-KR.html delete mode 100644 tips/references-to-components.html delete mode 100644 tips/self-closing-tag-ja-JP.html delete mode 100644 tips/self-closing-tag-ko-KR.html delete mode 100644 tips/self-closing-tag-ru-RU.html delete mode 100644 tips/self-closing-tag.html delete mode 100644 tips/style-props-value-px-ko-KR.html delete mode 100644 tips/style-props-value-px-ru-RU.html delete mode 100644 tips/style-props-value-px.html delete mode 100644 tips/use-react-with-other-libraries-ko-KR.html create mode 100644 tutorial/tutorial.html diff --git a/404.html b/404.html index 948cd4abe4..2ed1f44fdc 100644 --- a/404.html +++ b/404.html @@ -1,12 +1,14 @@ + + - Page Not Found | React - - + Page Not Found - React + + @@ -44,29 +46,29 @@
-
@@ -82,19 +84,51 @@
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
+ + + +
+Click here if you are not redirected. + diff --git a/blog/2013/11/06/community-roundup-10.html b/blog/2013/11/06/community-roundup-10.html index 7c8cf2fc22..4a9e6952a1 100644 --- a/blog/2013/11/06/community-roundup-10.html +++ b/blog/2013/11/06/community-roundup-10.html @@ -1,16 +1,19 @@ + + - Community Round-up #10 | React - - - + Community Round-up #10 - React Blog + + + - + @@ -44,61 +47,32 @@
+ +
+ + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Conferences +

+
+ +

React.js Conf 2015 #

+

January 28 & 29 in Facebook HQ, CA

+ +

Website - Schedule - Videos

+ + +

ReactEurope 2015 #

+

July 2 & 3 in Paris, France

+ +

Website - Schedule - Videos

+

Reactive 2015 #

+

November 2-4 in Bratislava, Slovakia

+ +

Website - Schedule

+

React.js Conf 2016 #

+

February 22 & 23 in San Francisco, CA

+ +

Website - Schedule - Videos

+

React Amsterdam 2016 #

+

April 16 in Amsterdam, The Netherlands

+ +

Website - Videos

+

ReactEurope 2016 #

+

June 2 & 3 in Paris, France

+ +

Website - Schedule

+

ReactRally 2016 #

+

August 25-26 in Salt Lake City, UT

+ +

Website - Schedule - Videos

+

ReactNext 2016 #

+

September 15 in Tel Aviv, Israel

+ +

Website - Schedule

+

ReactNL 2016 #

+

October 13 in Amsterdam, The Netherlands

+ +

Website

+

Reactive 2016 #

+

October 26-28 in Bratislava, Slovakia

+ +

Website

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/community/support.html b/community/support.html new file mode 100644 index 0000000000..e50e730975 --- /dev/null +++ b/community/support.html @@ -0,0 +1,214 @@ + + + + + + + + + Where To Get Support - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Where To Get Support +

+
+ +

React is worked on full-time by Facebook's product infrastructure and Instagram's user interface engineering teams. They're often around and available for questions.

+

Stack Overflow #

+

Many members of the community use Stack Overflow to ask questions. Read through the existing questions tagged with reactjs or ask your own!

+

Discussion forum #

+

For longer-form conversations about React, we've set up a discussion forum at discuss.reactjs.org. This forum is a great place for discussion about best practices and application architecture as well as the future of React. If you have an answerable code-level question, please post it to Stack Overflow instead.

+ +

In the forum there's also a category for job posts and a category for discussion of our weekly meeting notes.

+

Reactiflux Chat #

+

If you need an answer right away, check out the Reactiflux Discord community. There are usually a number of React experts there who can help out or point you to somewhere you might want to look.

+

Facebook and Twitter #

+

For the latest news about React, like us on Facebook and follow @reactjs on Twitter. In addition, you can use the #reactjs hashtag to see what others are saying or add to the conversation.

+ +
+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/community/videos.html b/community/videos.html new file mode 100644 index 0000000000..21439b319a --- /dev/null +++ b/community/videos.html @@ -0,0 +1,341 @@ + + + + + + + + + Videos - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Videos +

+
+ +

Introduction to React #

+

Tom Occhino and Jordan Walke introduce React at Facebook Seattle.

+ + +

Introducing React Native #

+

Tom Occhino reviews the past and present of React in 2015, and teases where it's going next.

+ + +

Rethinking Web App Development at Facebook #

+

Delivering reliable, high-performance web experiences at Facebook's scale has required us to challenge some long-held assumptions about software development. Watch this Facebook F8 2014 talk to learn how we abandoned the traditional MVC paradigm in favor of a more functional application architecture.

+ + +

Secrets of the Virtual DOM #

+

Pete Hunt at Mountain West JavaScript 2014 discusses why a virtual DOM was built for React, how it compares to other systems, and its relevance to the future of browser technologies.

+ + +

Rethinking Best Practices #

+

Pete Hunt's talk at JSConf EU 2013 covers three topics: throwing out the notion of templates and building views with JavaScript, “re-rendering” your entire application when your data changes, and a lightweight implementation of the DOM and events.

+ + +

High performance functional DOM programming #

+

Tech Talk by Pete Hunt at Meteor DevShop 11.

+ + +

Developing User Interfaces With React #

+

Steven Luscher at Super VanJS 2013.

+ + +

Introduction to React #

+

Stoyan Stefanov at LAWebSpeed meetup.

+ + +

Going big with React #

+

Areeb Malik investigates how React performs in a high stress situation, and how it helped his team build safe code on a massive scale.

+ +

+

Backbone + React + Middleman Screencast #

+

This screencast shows how to integrate Backbone with React using Backbone-React-Component.

+ + +

React, or how to make life simpler #

+

Tech talk by Alexander Solovyov at FrontEnd Dev Conf '14 (Russian).

+ + +

React and Flux: Building Applications with a Unidirectional Data Flow #

+

Facebook engineers Bill Fisher and Jing Chen talk about Flux and React at Forward JS 2014, and how using an application architecture with a unidirectional data flow cleans up a lot of their code.

+ + +

Server-Side Rendering of Isomorphic Apps at SoundCloud #

+

Walk-through by Andres Suarez on how SoundCloud is using React and Flux for server-side rendering.

+ + + +
+

Slides and sample code

+
+

CodeWinds Podcast #

+

Pete Hunt talked with Jeff Barczewski about React in CodeWinds Episode 4. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
02:08What is React and why use it?27:17Rendering HTML on the server with Node.js. Rendering backends
03:08The symbiotic relationship of ClojureScript and React29:20React evolved through survival of the fittest at Facebook
04:54The history of React and why it was created30:15Ideas for having state on server and client, using web sockets.
09:43Updating web page with React without using data binding32:05React-multiuser - distributed shared mutable state using Firebase
13:11Using the virtual DOM to change the browser DOM33:03Better debugging with React using the state transitions, replaying events
13:57Programming with React, render targets HTML, canvas, other34:08Differences from Web Components
16:45Working with designers. Contrasted with Ember and AngularJS34:25Notable companies using React
21:45JSX Compiler bridging HTML and React javascript35:16Could a React backend plugin be created to target PDF?
23:50Autobuilding JSX and in browser tools for React36:30Future of React, what's next?
24:50Tips and tricks to working with React, getting started39:38Contributing and getting help
+

JavaScript Jabber Podcast #

+

Pete Hunt and Jordan Walke talked about React in JavaScript Jabber 73. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
01:34Pete Hunt Introduction23:06Supporting Node.js
02:45Jordan Walke Introduction24:03rendr
04:15React26:02JSX
06:3860 Frames Per Second30:31requestAnimationFrame
09:34Data Binding34:15React and Applications
12:31Performance38:12React Users Khan Academy
17:39Diffing Algorithm39:53Making it work
19:36DOM Manipulation
+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/contributing/codebase-overview.html b/contributing/codebase-overview.html index 958417fa11..37fbbe2aac 100644 --- a/contributing/codebase-overview.html +++ b/contributing/codebase-overview.html @@ -1,12 +1,14 @@ + + - Codebase Overview | React - - + Codebase Overview - React + + @@ -44,398 +46,31 @@
- - - -
-
+ + + -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Add-ons -

-
- -

React.addons è il luogo in cui parcheggiamo utili strumenti per costruire applicazioni React. Questi strumenti devono essere considerati sperimentali ma saranno eventualmente inclusi nel nucleo o una libreria ufficiale di utilities:

- -
    -
  • TransitionGroup e CSSTransitionGroup, per gestire animazioni e transizioni che sono solitamente difficili da implementare, come ad esempio prima della rimozione di un componente.
  • -
  • LinkedStateMixin, per semplificare la coordinazione tra lo stato del componente e l'input dell'utente in un modulo.
  • -
  • cloneWithProps, per eseguire una copia superficiale di componenti React e cambiare le loro proprietà.
  • -
  • createFragment, per creare un insieme di figli con chiavi esterne.
  • -
  • update, una funzione di utilità che semplifica la gestione di dati immutabili in JavaScript.
  • -
  • PureRenderMixin, un aiuto per incrementare le prestazioni in certe situazioni.
  • -
- -

Gli add-ons elencati di seguito si trovano esclusivamente nella versione di sviluppo (non minificata) di React:

- -
    -
  • TestUtils, semplici helper per scrivere dei test case (soltanto nella build non minificata).
  • -
  • Perf, per misurare le prestazioni e fornirti suggerimenti per l'ottimizzazione.
  • -
- -

Per ottenere gli add-on, usa react-with-addons.js (e la sua controparte non minificata) anziché il solito react.js.

- -

Quandi si usa il pacchetto react di npm, richiedi semplicemente require('react/addons') anziché require('react') per ottenere React con tutti gli add-on.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/addons-ja-JP.html b/docs/addons-ja-JP.html deleted file mode 100644 index f719d52482..0000000000 --- a/docs/addons-ja-JP.html +++ /dev/null @@ -1,515 +0,0 @@ - - - - - - - アドオン | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- アドオン -

-
- -

React.addons はReactのアプリケーションを作成する上で便利なユーティリティを置いておくための場所です。 それらは実験的なものであると考えられるべきです。 しかし、ゆくゆくはコアに入ってくるか、以下のような承認されたユーティリティとなるでしょう。

- -
    -
  • アニメーションや推移を扱うTransitionGroupCSSTransitionGroupは多くの場合実行するのが簡単ではありません。例えば、コンポーネントの削除の前などは。
  • -
  • LinkedStateMixinはユーザのフォームの入力データとコンポーネントのstateの間の調整を単純化します。
  • -
  • cloneWithPropsはReactのコンポーネントのシャローコピーを作成したり、それらのpropsを変更したりします。
  • -
  • createFragmentは外部のキー化された子要素のセットを作成します。
  • -
  • updateはJavaScriptでイミュータブルなデータを扱うことを簡単にするヘルパーの関数です。
  • -
  • PureRenderMixinは特定のシチュエーションでパフォーマンスを改善します。 -以下のアドオンはReactだけの開発版(縮小されていない版)です。

  • -
  • TestUtilsはテストケースを記述する単純なヘルパーです(縮小されていないビルドのみ)。

  • -
  • Perfはパフォーマンスを測り、どこを最適化するかのヒントを与えます。

  • -
- -

アドオンを使うには、共通の react.js を使うよりも react-with-addons.js (とその縮小されたもの)を使ってください。

- -

npmからReactのパッケージを使う際には、Reactと全てのアドオンを使うために require('react') を使う代わりに、単純に require('react/addons') を使ってください。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/addons-ko-KR.html b/docs/addons-ko-KR.html deleted file mode 100644 index f41240c3cc..0000000000 --- a/docs/addons-ko-KR.html +++ /dev/null @@ -1,517 +0,0 @@ - - - - - - - 애드온 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 애드온 -

-
- -

React 애드온은 React 앱을 만드는 데 유용한 유틸리티의 모음입니다. 실험적인 기능으로 취급해야 하고 코어보다 더 자주 변경될 수 있습니다.

- -
    -
  • TransitionGroupCSSTransitionGroup은 예를 들면 컴포넌트 삭제 직전의 트랜지션 처럼, 구현하기 까다로운 애니메이션과 트랜지션을 다룹니다.
  • -
  • LinkedStateMixin는 사용자 입력과 컴포넌트의 state사이의 조정(coordination)을 단순화 합니다.
  • -
  • cloneWithProps는 React 컴포넌트를 얕은 복사를 하고 props를 변경합니다.
  • -
  • createFragment는 외부에서 키가 할당된 자식들의 모음을 만듭니다.
  • -
  • update는 JavaScript안에서 불변 데이터를 다루기 쉽게하는 헬퍼 함수입니다.
  • -
  • PureRenderMixin는 특정 상황에서 성능을 향상시켜 줍니다.
  • -
- -

밑에 있는 애드온은 React 개발 (압축되지 않은) 버전에서만 사용가능 합니다.

- -
    -
  • TestUtils는 테스트 케이스를 적기 위한 간단한 헬퍼입니다. (압축되지 않은 빌드에서만 사용가능)
  • -
  • Perf는 성능을 측정하고, 최적화를 위한 힌트를 제공합니다.
  • -
- -

애드온을 쓰려면, npm에서 각각 설치하세요.(예를 들면, npm install react-addons-pure-render-mixin) npm을 사용하지 않는 애드온 사용법에 대한 지원은 없습니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/addons-zh-CN.html b/docs/addons-zh-CN.html deleted file mode 100644 index 0cc25eb2ce..0000000000 --- a/docs/addons-zh-CN.html +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - - 插件 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 插件 -

-
- -

React插件是一系列的用来构建 React app的有用模块。 这些应该被认为是实验性的 并趋向于比core变动更频繁。

- -
    -
  • TransitionGroupCSSTransitionGroup, 用来处理通常不能简单实现的动画和转换,比如在组件移除之前。
  • -
  • LinkedStateMixin, 简化用户的表单输入数据与组件状态的协调。
  • -
  • cloneWithProps, 创建React组件的浅拷贝并改变它们的props。
  • -
  • createFragment, 创建一组外键的子级。
  • -
  • update, 一个使不可变数据在JavaScript里更易处理的辅助函数。
  • -
  • PureRenderMixin, 一个特定情况下的性能优化器。
  • -
  • shallowCompare, 一个辅助函数,用来对 props 和 state在组件里 执行浅比较 以决定一个组件是否应该更新。
  • -
- -

下面的插件只存在开发版(未压缩)React中:

- -
    -
  • TestUtils, 用于写测试用例的简单的辅助工具。
  • -
  • Perf, 一个用于查找优化机会的性能分析工具。
  • -
- -

要获取插件,单独从npm安装他们(例如 npm install react-addons-pure-render-mixin).我们不支持使用插件如果你没有用npm.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/addons.html b/docs/addons.html index 5b0ce9eee9..ebb042794e 100644 --- a/docs/addons.html +++ b/docs/addons.html @@ -1,12 +1,14 @@ + + - Add-ons | React - - + Add-Ons - React + + @@ -44,31 +46,78 @@
-
+
+ Edit on GitHub +

+ Add-Ons +

+
+ +

The React add-ons are a collection of useful utility modules for building React apps. These should be considered experimental and tend to change more often than the core.

+ + + +

The add-ons below are in the development (unminified) version of React only:

+ +
    +
  • Perf, a performance profiling tool for finding optimization opportunities.
  • +
  • ReactTestUtils, simple helpers for writing test cases.
  • +
+

Legacy Add-ons #

+

The add-ons below are considered legacy and their use is discouraged.

+ + +

Deprecated Add-ons #

+

LinkedStateMixin has been deprecated.

+

Using React with Add-ons #

+

If using npm, you can install the add-ons individually from npm (e.g. npm install react-addons-test-utils) and import them:

+
import Perf from 'react-addons-perf'; // ES6
+var Perf = require('react-addons-perf'); // ES5 with npm
+
+

When using a CDN, you can use react-with-addons.js instead of react.js:

+
<script src="https://unpkg.com/react@15/dist/react-with-addons.js"></script>
+
+

The add-ons will be available via the React.addons global (e.g. React.addons.TestUtils).

+ + +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,63 +352,57 @@
+ - -
- Edit on GitHub -

- Add-ons -

-
- -

The React add-ons are a collection of useful utility modules for building React apps. These should be considered experimental and tend to change more often than the core.

- - - -

The add-ons below are in the development (unminified) version of React only:

- - - -

To get the add-ons, install them individually from npm (e.g., npm install react-addons-pure-render-mixin). We don't support using the addons if you're not using npm.

- - -
- - ← Prev - - - Next → - -
-
- - -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Performance Avanzata -

-
- -

Una tra le prime domande che la gente si pone quando considera React per un progetto è se l'applicazione sarà altrettanto veloce e scattante di una versione equivalente non basata su React. L'idea di ripetere il rendering di un intero sottoalbero di componenti in risposta a ciascun cambiamento dello stato rende la gente curiosa se questo processo influisce negativamente sulle prestazioni. React utilizza diverse tecniche intelligenti per minimizzare il numero di operazioni costose sul DOM richieste dall'aggiornamento della UI.

-

Evitare di riconciliare il DOM #

-

React fa uso di un DOM virtuale, che è un descrittore di un sottoalbero DOM visualizzato nel browser. Questa rappresentazione parallela permette a React di evitare di creare nodi DOM e accedere nodi esistenti, che è di gran lunga più lento di operazioni su oggetti JavaScript. Quando le proprietà di un componente o il suo stato cambiano, React decide se un'aggiornamento effettivo del DOM sia necessario costruendo un nuovo virtual DOM e confrontandolo con quello vecchio. Solo nel caso in cui non siano uguali, React riconcilierà il DOM, applicando il minor numero di mutamenti possibile.

- -

In aggiunta a questo, React offre una funzione per il ciclo di vita del componente, shouldComponentUpdate, che viene scatenata prima che il processo di ri-rendering cominci (il confronto del DOM virtuale e una possibile eventuale riconciliazione del DOM), dando allo sviluppatore la possibilità di cortocircuitare questo processo. L'implementazione predefinita di questa funzione restituisce true, lasciando che React effettui l'aggiornamento:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return true;
-}
-
-

Tieni in mente che React invocherà questa funzione abbastanza spesso, quindi l'implementazione deve essere veloce.

- -

Supponiamo che hai un'applicazione di messaggistica con parecchi thread di conversazioni. Supponi che solo uno dei thread sia cambiato. Se implementassimo shouldComponentUpdate sul componente ChatThread, React potrebbe saltare la fase di rendering per gli altri thread:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  // TODO: restituisci true se il thread attuale è diverso
-  // da quello precedente.
-}
-
-

Quindi, riassumendo, React evita di effettuare operazioni costose sul DOM richieste a riconciliare sottoalberi del DOM, permettendo all'utente di cortocircuitare il processo usando shouldComponentUpdate, e, per i casi in cui si debba aggiornare, confrontando i DOM virtuali.

-

shouldComponentUpdate in azione #

-

Ecco un sottoalbero di componenti. Per ciascuno di essi viene indicato cosa shouldComponentUpdate ha restituito e se i DOM virtuali siano equivalenti o meno. Infine, il colore del cerchio indica se il componente sia stato riconciliato o meno.

- -
- -

Nell'esempio precedente, dal momento che shouldComponentUpdate ha restituito false per il sottoalbero di radice C2, React non ha avuto bisogno di generare il nuovo DOM virtuale, e quindi non ha nemmeno avuto bisogno di riconciliare il DOM. Nota che React non ha nemmeno avuto bisogno di invocare shouldComponentUpdate su C4 e C5.

- -

Per C1 e C3, shouldComponentUpdate ha restituito true, quindi React è dovuto scendere giù fino alle foglie e controllarle. Per C6 ha restituito true; dal momento che i DOM virtuali non erano equivalenti, ha dovuto riconciliare il DOM. -L'ultimo caso interessante è C8. Per questo nodo React ha dovuto calcolare il DOM virtuale, ma dal momento che era uguale al vecchio, non ha dovuto riconciliare il suo DOM.

- -

Nota che React ha dovuto effettuare mutazioni del DOM soltanto per C6, che era inevitabile. Per C8, lo ha evitato confrontando i DOM virtuali, e per il sottoalbero di C2 e C7, non ha neppure dovuto calcolare il DOM virtuale in quanto è stato esonerato da shouldComponentUpdate.

- -

Quindi, come dovremmo implementare shouldComponentUpdate? Supponiamo di avere un componente che visualizza soltanto un valore stringa:

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.string.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value}</div>;
-  }
-});
-
-

Potremmo facilmente implementare shouldComponentUpdate come segue:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value !== nextProps.value;
-}
-
-

Finora tutto a posto, maneggiare queste semplici strutture proprietà e stato è molto facile. Potremmo anche generalizzare un'implementazione basata sull'uguaglianza superficiale e farne il mix dentro i componenti. Infatti, React fornisce già una tale implementazione: PureRenderMixin.

- -

Ma che succede se le proprietà o lo stato del tuo componente sono strutture dati mutevoli? Supponiamo che la proprietà che il componente riceve sia, anziché una stringa come 'bar', un oggetto JavaScript che contiene una stringa, come { foo: 'bar' }:

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.object.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value.foo}</div>;
-  }
-});
-
-

L'implementazione di shouldComponentUpdate che avevamo prima non funzionerebbe sempre come ci aspettiamo:

-
// assumiamo che this.props.value sia { foo: 'bar' }
-// assumiamo che nextProps.value sia { foo: 'bar' },
-// ma questo riferimento è diverso da this.props.value
-this.props.value !== nextProps.value; // true
-
-

Il problema è che shouldComponentUpdate restituirà true quando la proprietà non è in realtà cambiata. Per risolvere questo problema, potremmo proporre questa implementazione alternativa:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value.foo !== nextProps.value.foo;
-}
-
-

In breve, abbiamo finito per effettuare un confronto in profondità per assicurarci di accorgerci correttamente dei cambiamenti. In termini di prestazioni, questo approccio è molto costoso. Non scala in quanto dovremmo scrivere codice diverso per valutare l'uguaglianza in profondità per ciascun modello. Inoltre, potrebbe anche non funzionare per nulla se non gestiamo correttamente i riferimenti agli oggetti. Supponiamo che il componente sia usato da un genitore:

-
React.createClass({
-  getInitialState: function() {
-    return { value: { foo: 'bar' } };
-  },
-
-  onClick: function() {
-    var value = this.state.value;
-    value.foo += 'bar'; // ANTI-PATTERN!
-    this.setState({ value: value });
-  },
-
-  render: function() {
-    return (
-      <div>
-        <InnerComponent value={this.state.value} />
-        <a onClick={this.onClick}>Click me</a>
-      </div>
-    );
-  }
-});
-
-

La prima volta che viene effettuato il rendering del componente interno, la sua proprietà value avrà il valore { foo: 'bar' }. Se l'utente clicca l'ancora, lo stato del componente genitore sarà aggiornato a { value: { foo: 'barbar' } }, scatenando il processo di ri-rendering sul componente interno, il quale riceverà { foo: 'barbar' } come il nuovo valore della proprietà.

- -

Il problema è che, dal momento che il genitore e il componente interno condividono un riferimento allo stesso oggetto, quando l'oggetto viene modificato nella riga 2 della funzione onClick, la proprietà che il componente interno possedeva cambierà anch'essa. Quindi, quando il processo di ri-rendering inizia, e shouldComponentUpdate viene invocato, this.props.value.foo sarà uguale a nextProps.value.foo, perché infatti, this.props.value si riferisce allo stesso oggetto di nextProps.value.

- -

Di conseguenza, dal momento che non ci accorgiamo del cambiamento della proprietà e cortocircuitiamo il processo di ri-rendering, la UI non sarà aggiornata da 'bar' a 'barbar'.

-

Immutable-js viene in nostro soccorso #

-

Immutable-js è una libreria di collezioni JavaScript scritta da Lee Byron, che Facebook ha recentemente rilasciato come open source. Fornisce collezioni immutabili e persistenti attraverso condivisione strutturale. Vediamo cosa significano queste proprietà:

- -
    -
  • Immutabile: una volta creata, una collezione non può essere alterata in un momento successivo.
  • -
  • Persistente: nuove collezioni possono essere create da una collezione precedente e una mutazione come un assegnamento. La collezione originale è ancora valida dopo che la nuova collezione è stata creata.
  • -
  • Condivisione Strutturale: nuove collezioni sono create riutilizzando quanto più possibile della stessa struttura della collezione originale, riducendo le operazioni di copia al minimo, per ottenere efficienza spaziale e prestazioni accettabili. Se la nuova collezione è identica all'originale, l'originale è spesso restituita.
  • -
- -

L'immutabilità ci permette di tenere traccia dei cambiamenti in modo economico; un cambiamento risulterà sempre in un nuovo oggetto, quindi dobbiamo soltanto controllare se il riferimento all'oggeto sia cambiato. Ad esempio, in questo codice regolare JavaScript:

-
var x = { foo: "bar" };
-var y = x;
-y.foo = "baz";
-x === y; // true
-
-

Sebbene y sia stato modificato, dal momento che si tratta di un riferimento allo stesso oggetto di x, questo confronto restituisce true. Tuttavia, questo codice potrebbe essere scritto usando immutable-js come segue:

-
var SomeRecord = Immutable.Record({ foo: null });
-var x = new SomeRecord({ foo: 'bar'  });
-var y = x.set('foo', 'baz');
-x === y; // false
-
-

In questo caso, poiché un nuovo riferimento è restituito quando si modifica x, possiamo assumere in tutta sicurezza che x sia cambiato.

- -

Un'altra maniera possibile di tener traccia dei cambiamenti potrebbe essere il dirty checking, ovvero usare un flag impostato dai metodi setter. Un problema con questo approccio è che ti forza ad usare i setter e scrivere un sacco di codice aggiuntivo, oppure instrumentare in qualche modo le tue classi. In alternativa, puoi effettuare una copia profonda dell'oggetto immediatamente prima della mutazione ed effettuare un confronto in profondità per determinare se vi è stato un cambiamento oppure no. Un problema con questo approccio è che sia deepCopy che deepCompare sono operazioni costose.

- -

Quindi, le strutture dati Immutable ti forniscono una maniera economica e concisa di osservare i cambiamenti degli oggetti, che è tutto ciò che ci serve per implementare shouldComponentUpdate. Pertanto, se modelliamo gli attributi delle proprietà e dello stato usando le astrazioni fornite da immutable-js saremo in grado di usare PureRenderMixin e ottenere un grande aumento di prestazioni.

-

Immutable-js e Flux #

-

Se stai usando Flux, dovresti cominciare a scrivere i tuoi store usando immutable-js. Dài un'occhiata alla API completa.

- -

Vediamo una delle possibili maniere di modellare l'esempio dei thread usando strutture dati Immutable. Anzitutto, dobbiamo definire un Record per ciascuna delle entità che desideriamo modellare. I Record sono semplicemente contenitori immutabili che contengono valori per un insieme specifico di campi:

-
var User = Immutable.Record({
-  id: undefined,
-  name: undefined,
-  email: undefined
-});
-
-var Message = Immutable.Record({
-  timestamp: new Date(),
-  sender: undefined,
-  text: ''
-});
-
-

La funzione Record riceve un oggetto che definisce i campi che l'oggetto possiede e i loro valori predefiniti.

- -

Lo store dei messaggi potrebbe tenere traccia degli utenti e dei messaggi usando due liste:

-
this.users = Immutable.List();
-this.messages = Immutable.List();
-
-

Dovrebbe essere abbastanza banale implementare funzioni che gestiscono ciascun tipo di payload. Ad esempio, quando lo store vede un payload che rappresenta un messaggio, possiamo semplicemente creare un nuovo record e metterlo in coda alla lista di messaggi:

-
this.messages = this.messages.push(new Message({
-  timestamp: payload.timestamp,
-  sender: payload.sender,
-  text: payload.text
-});
-
-

Nota che dal momento che le strutture dati sono immutabili, dobbiamo assegnare il valore di ritorno del metodo push a this.messages.

- -

Dal punto di vista di React, se usiamo strutture dati immutable-js anche per contenere lo stato del componente, possiamo fare il mix di PureRenderMixin in tutti i nostri componenti e cortocircuitare il processo di ri-rendering.

- - -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/advanced-performance-ja-JP.html b/docs/advanced-performance-ja-JP.html deleted file mode 100644 index adca0d620e..0000000000 --- a/docs/advanced-performance-ja-JP.html +++ /dev/null @@ -1,649 +0,0 @@ - - - - - - - 先進的なパフォーマンス | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 先進的なパフォーマンス -

-
- -

Reactをプロジェクトで使用しようとする際にまず最初に気になるのは、アプリケーションがReactを使用しないバージョンと比べて、同じくらい速くてレスポンシブであるかどうかということです。ステータスの変更毎にレスポンスでコンポーネントのサブツリーの全てを再度レンダリングするという考え方によって、このプロセスがパフォーマンスにネガティブな影響を与えるのではないかと人々は不安に思います。ReactはUIを更新するのに必要な、コストのかかる多くのDOMの操作を最小限にするためのいくつかの賢い技術を使用します。

-

DOMを一致させることを防ぐこと #

-

ReactはブラウザでレンダリングされるDOMのサブツリーの記述語である virtual DOM を使用しています。この2つの表現によってReactは、JavaScriptのオブジェクトの操作よりも遅い、DOMノードを作成したり存在しているDOMノードにアクセスすることを防いでいます。コンポーネントの propsstate が変更された時、Reactは新しいvirtual DOMを構成して、それを古いものと比較することによって、実際のDOMの更新が必要かどうか決定します。それらが同じものでなかった場合にのみ、ReactはDOMを一致させ、最小限の変更を適用します。 -この最上位で、Reactはコンポーネントライフサイクルファンクションである shouldComponentUpdate を提供します。これは、再度レンダリングを行うプロセス(virtual DOMの比較と起こり得る最終的なDOMの一致)が始まる前に誘発されます。そして、開発者にこのプロセスの循環を短くすることを可能にします。デフォルトのこの関数の実行時にはReactが更新を行って、以下のように true が返ります。

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return true;
-}
-
-

Reactがとても頻繁にこの関数を呼び出すので、実行が速いものである必要があることを頭に置いておいてください。

- -

いくつかのチャットのスレッドを持つメッセージングのアプリケーションを持っていると仮定してください。そして、スレッドのうち1つだけが変更されたと考えてください。 ChatThread コンポーネントで shouldComponentUpdate を実行した際には、Reactは以下のように、他のスレッドのレンダリングステップをスキップできます。

-
shouldComponentUpdate: function(nextProps, nextState) {
-  // TODO: 現在のチャットスレッドが以前のものと
-  // 異なっているかどうかをリターンする。
-}
-
-

つまり、要約すると、ReactはDOMのサブツリーを一致させる必要があるためにコストのかかるDOMの操作を実行するのを避けます。 shouldComponentUpdate を使用して、このプロセスを短縮することができます。そして、virtual DOMを比較して、更新すべきDOMだけを更新します。

-

shouldComponentUpdate の実行 #

-

以下はコンポーネントのサブツリーです。1つ1つは shouldComponentUpdate が何をリターンするかとvirtual DOMが同じものであるかどうかを示しています。最終的には、円の色が、コンポーネントを一致させる必要があるかどうかを示しています。

- -
- -

上記の例では、C2の上の shouldComponentUpdatefalse を返しているので、Reactは新しいvirtual DOMを生成する必要はありません。そして、それゆえ、DOMを一致させる必要もありません。C4とC5についても、Reactが shouldComponentUpdate を実行する必要がないことに注意してください。

- -

C1とC3の shouldComponentUpdatetrue を返すので、Reactは葉の部分まで降りてそれらのチェックを行います。C6が true を返すので、virtual DOMが同じものではなくなり、DOMを一致させる必要があります。最後の興味深いケースはC8です。このノードについては、Reactはvirtual DOMを計算する必要がありますが、古いものと同じであるため、DOMと一致させる必要はありません。

- -

ReactがDOMを変化させるのはC6だけであることに注意してください。これは避けられません。C8は、virtual DOMの比較から解放されています。C2のサブツリーとC7も同様です。shouldComponentUpdate から解放されているので、virtual DOMの比較を行う必要はありません。

- -

それでは、私たちはどのように shouldComponentUpdate を実行すべきでしょうか?ある文字列の値をただレンダリングするコンポーネントの場合について見てみましょう。

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.string.isRequired
-  },
-
-  render: function() {
-    return <div>this.props.value</div>;
-  }
-});
-
-

以下のように簡単に shouldComponentUpdate を実行することができます。

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value !== nextProps.value;
-}
-
-

これまでは順調でした。以上のような、単純なpropsやstateの構造を扱うことは簡単です。浅い同一性に基づいて実行したり、コンポーネントに組み込んだりもできます。実際、Reactはそのような実行のためのMixinを既に提供しています。PureRenderMixinです。

- -

しかし、コンポーネントのpropsやstateが変更される可能性がある場合はどうでしょうか?propが bar のような文字列ではなく、コンポーネント受け取ったものであると考えてみると、 { foo: 'bar' } のような文字列を含んだJavaScriptのオブジェクトになります。

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.object.isRequired
-  },
-
-  render: function() {
-    return <div>this.props.value.foo</div>;
-  }
-});
-
-

今までに述べてきた shouldComponentUpdate の実行は常に想定した通りに動くとは限りません。

-
// this.props.value が { foo: 'bar' } であると仮定
-// nextProps.value が { foo: 'bar' } であると仮定
-// しかし、この参照は this.props.value とは異なります。
-this.props.value !== nextProps.value; // true
-
-

問題は、 shouldComponentUpdate が、propが実際には変化していない場合にも true を返すことです。これを修正するために、以下のような代替の実行を行うことができます。

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value.foo !== nextProps.value.foo;
-}
-
-

基本的には、厳密に変更を追跡することを明確にするために、深い比較を行うことになります。パフォーマンスの点では、このアプローチはとてもコストがかかります。これは、それぞれのモデルに対して間違った深い同一性のコードを書いているであろうときには、スケールしません。その最上部では、オブジェクトの参照を注意深く見ていなければ、動作しさえしません。以下のコンポーネントが親から使用されていると考えてください。

-
React.createClass({
-  getInitialState: function() {
-    return { value: { foo: 'bar' } };
-  },
-
-  onClick: function() {
-    var value = this.state.value;
-    value.foo += 'bar'; // アンチパターン!
-    this.setState({ value: value });
-  },
-
-  render: function() {
-    return (
-      <div>
-        <InnerComponent value={this.state.value} />
-        <a onClick={this.onClick}>Click me</a>
-      </div>
-    );
-  }
-});
-
-

はじめに、内部のコンポーネントがレンダリングされます。それは、valueというプロパティとして { foo: 'bar' } を保有します。ユーザがアンカーをクリックした際には、親のコンポーネントのstateが { value: { foo: 'barbar' } } にアップデートされるでしょう。そして、新しいvalueのプロパティとして、 { foo: 'barbar' } を受け取る、内部のコンポーネントの再レンダリングのプロセスのトリガーとなります。

- -

問題は、親と内部のコンポーネントが同じオブジェクトへの参照を共有していることです。オブジェクトが onClick 関数の2行目で変更された時には、内部のコンポーネントが保有しているプロパティが変更されるでしょう。そのため、再レンダリングのプロセスが始まった時と、 shouldComponentUpdate が呼び出された時には、 this.props.value.foonextProps.value.foo と同じものになるでしょう。そのため、実際は、 this.props.valuenextProps.value と同じオブジェクトを参照します。

- -

結果として、プロパティの変更と再レンダリングのプロセスを省略ができなかったので、UIは 'bar' から 'barbar' にアップデートされないでしょう。

-

助けとなるImmutable-js #

-

Immutable-jsはLee Byronによって作成されたJavaScriptのコレクションのライブラリです。Facebookが最近オープンソース化しました。これは、 構造の共有 を通して、不変の状態を保ち続ける コレクションを提供します。以下のプロパティが何を意味するか見ていきましょう。

- -
    -
  • Immutable: 一度作成されたら、コレクションは変更できません。
  • -
  • Persistent: 新しいコレクションは以前のコレクションかsetのような変化によってのみ作成されます。元となるコレクションは新しいコレクションが作成された後も使用可能です。
  • -
  • Structural Sharing: 新しいコレクションは元のコレクションとなるべく同じ構造を持って作成されます。パフォーマンスが効率的で許容できるものであるように、コピーを少なくします。新しいコレクションが元のものと同じである場合は、多くの場合元のものがリターンされます。
  • -
- -

不変性によって、変更を追跡するコストが下がります。変更は常に新しいオブジェクトを生むので、オブジェクトの参照が変更されたかどうかを確認しさえすればよいのです。例えば、以下のような一般的なJavaScriptのコードにおいては、

-
var x = { foo: "bar" };
-var y = x;
-y.foo = "baz";
-x === y; // true
-
-

y は編集されていますが、x と同じオブジェクトを参照しているので、それらの比較は true を返します。しかし、以下のコードはimmutable-jsを使用すると以下のように記述されます。

-
var SomeRecord = Immutable.Record({ foo: null });
-var x = new SomeRecord({ foo: 'bar'  });
-var y = x.set('foo', 'baz');
-x === y; // false
-
-

このケースでは、 x を変更する時に新しい参照が返されているので、 x が変更されたことを安全に認識することができます。

- -

変更を追跡する他の方法は、セッタによるフラグセットを保持することでダーティーチェックを行うことです。このアプローチの問題は、追加のコードを多く書いた場合やクラスの編集をいくつか行った場合でもセッタの使用が強制されることです。代わりに、変化の直前にオブジェクトをディープコピーし、変更が有ろうと無かろうと、その特定のために深い比較を行うことができます。このアプローチの問題は、ディープコピーと深い比較の両方とも、コストの高い操作であることです。

- -

そのため、不変なデータ構造によって、オブジェクトの変更を追跡するためのコストの低く、冗長ではない方法が提供されます。私たちがすべきなのは shouldComponentUpdate を実行することだけです。それゆえ、immutable-jsに提供される抽象化を使用して、propsやstate属性を形作る場合は、 PureRenderMixin を使用して、パフォーマンスの向上を行うことができます。

-

Immutable-js と Flux #

-

Fluxを使用している場合には、immutable-jsを使用して書き直すべきです。API一覧をご覧ください。

- -

不変のデータ構造を使用したスレッドの例を形作る、ある方法を見ていきましょう。はじめに、形作ろうとしているエンティティのそれぞれに Record を定義する必要が有ります。Record はあるフィールドのセットの値を保持している、ただの不変なコンテナです。

-
var User = Immutable.Record({
-  id: undefined,
-  name: undefined,
-  email: undefined
-});
-
-var Message = Immutable.Record({
-  timestamp: new Date(),
-  sender: undefined,
-  text: ''
-});
-
-

Record 関数はオブジェクトが保有しているフィールドとデフォルトの値を定義するオブジェクトを受け取ります。

- -

メッセージの ストア は以下のように2つのリストを使用して users と messages を追跡し続けることができます。

-
this.users = Immutable.List();
-this.messages = Immutable.List();
-
-

それぞれの ペイロードの 型を調査することはとても単純で、関数を実行するだけです。例えば、ストアが新しいメッセージを代表するペイロードを調べるときには、新しいレコードを作成し、それを以下のような messages のリストとして適用するだけです。

-
this.messages = this.messages.push(new Message({
-  timestamp: payload.timestamp,
-  sender: payload.sender,
-  text: payload.text
-});
-
-

データ構造が不変であることで、push関数の結果を this.messages にアサインする必要があることに注意してください。

- -

Reactの側では、 immutable-js のデータ構造をコンポーネントの state を保持するために使用する場合は、 PureRenderMixin をコンポーネントにミックスし、再レンダリングのプロセスを短縮することもできます。

- - -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/advanced-performance-ko-KR.html b/docs/advanced-performance-ko-KR.html deleted file mode 100644 index f005de57c5..0000000000 --- a/docs/advanced-performance-ko-KR.html +++ /dev/null @@ -1,651 +0,0 @@ - - - - - - - 성능 심화 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 성능 심화 -

-
- -

React를 도입하려 할 때 많은 사람이 묻는 첫 번째 질문은 React를 사용하지 않을 때처럼 애플리케이션이 빠르고 반응성도 좋을 것이냐는 것입니다. 모든 상태변화에 대해 컴포넌트의 하위 트리를 전부 다시 렌더링하는 아이디어에 대해 사람들은 이 프로세스가 성능에 부정적인 영향을 줄 것으로 생각하지만, React는 여러 가지 영리한 방법을 통해 UI를 업데이트하는데 필요한 비싼 DOM 조작을 최소화합니다.

-

DOM 조정 회피 #

-

React는 브라우저에서 렌더된 DOM 하위 트리의 서술자 개념인 가상의 DOM을 사용합니다. 이 병렬적인 서술체는 React가 DOM 노드를 생성하거나 이미 존재하는 DOM 노드에 접근하는 것(JavaScript 객체를 조작하는 것보다 느리죠)을 피하게 해 줍니다. 컴포넌트의 props나 state가 변경되면 React는 새로운 가상의 DOM을 구성해 이전의 것과 비교해서 실제 DOM 업데이트가 필요한지 결정합니다. 가능한 적게 변화를 적용하기 위해, React는 둘이 다를 경우에만 DOM을 조정할 것입니다.

- -

이에 더해, React는 컴포넌트 생명주기 함수인 shouldComponentUpdate를 제공합니다. 이는 다시 렌더링하는 프로세스(가상 DOM 비교와 어쩌면 일어날 DOM 조정)가 일어나기 직전에 일어나며 개발자가 프로세스를 중단할 수 있게 합니다. 이 함수의 기본구현은 true를 반환해 React가 업데이트를 수행하도록 합니다.

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return true;
-}
-
-

React가 이 함수를 자주 호출한다는 것을 명심하십시오. 따라서 구현체는 빨라야 합니다.

- -

대화 스레드가 여럿 돌고 있는 메시지처리 애플리케이션을 생각해 봅시다. 오직 하나의 스레드만이 변경되었다고 가정해 보죠. ChatThreadshouldComponentUpdate를 구현했다면 React는 다른 스레드의 렌더링 프로세스를 건너뛸 수 있습니다.

-
shouldComponentUpdate: function(nextProps, nextState) {
-  // TODO: 현재의 대화 스레드가 이전의 것과 다른지 아닌지를 반환한다
-}
-
-

정리하자면, React는 사용자가 shouldComponentUpdate를 사용해 렌더링 프로세스를 중단하고 가상의 DOM과 비교해 업데이트 여부를 결정해서 DOM의 하위 트리를 조정하는 비싼 DOM 조작을 피하도록 합니다.

-

shouldComponentUpdate 실전 #

-

다음은 컴포넌트의 하위 트리입니다. 각각은 shouldComponentUpdate의 반환값(SCU)과 가상의 DOM과의 동일성(vDOMEq)을 표시합니다. 마지막으로, 원의 색은 컴포넌트가 조정되었는지를 표시합니다.

- -
- -

위의 예시에서, C2를 루트로 하는 하위 트리에 대해 shouldComponentUpdatefalse를 반환했기 때문에 React는 새로운 가상의 DOM을 만들 필요가 없습니다. 따라서 DOM을 조정할 필요도 없습니다. React가 C4와 C5에는 shouldComponentUpdate를 요청하지도 않은 것을 확인하세요.

- -

C1과 C3의 shouldComponentUpdatetrue를 반환했기 때문에 React는 하위 노드로 내려가 그들을 확인합니다. C6는 true를 반환했네요; 이는 가상의 DOM과 같지 않기 때문에 DOM의 조정이 일어났습니다. 마지막으로 흥미로운 사례는 C8입니다. React가 이 노드를 위해 가상의 DOM을 작동했지만, 노드가 이전의 것과 일치했기 때문에 DOM의 조정을 일어나지 않았습니다.

- -

React가 C6에만 DOM 변경을 수행한 것을 확인하세요. 이는 필연적이었습니다. C8의 경우는, 가상의 DOM과 비교를 해 제외되었고, C2의 하위 트리와 C7은 shouldComponentUpdate 단계에서 제외되어 가상의 DOM은 구동조차 되지 않았습니다.

- -

자 그럼, 어떻게 shouldComponentUpdate를 구현해야 할까요? 문자열 값을 렌더하는 컴포넌트를 생각해보죠.

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.string.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value}</div>;
-  }
-});
-
-

다음과 같이 간단히 shouldComponentUpdate를 구현해 볼 수 있습니다:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value !== nextProps.value;
-}
-
-

여기까지는 좋습니다. 간단한 props/state 구조를 다루기는 쉽습니다. 단순한 등식비교 구현을 일반화하고 이를 컴포넌트에 혼합할 수도 있습니다. 사실, React는 이미 그런 구현을 제공합니다: PureRenderMixin.

- -

하지만 만약 컴포넌트의 props나 state가 가변적인 데이터 구조로 되어 있다면 어떨까요? 컴포넌트의 prop으로 'bar'같은 문자열 대신에 { foo: 'bar' }처럼 문자열을 포함한 JavaScript 객체를 전달받는다고 해봅시다.

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.object.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value.foo}</div>;
-  }
-});
-
-

전에 구현했던 shouldComponentUpdate는 언제나 예상대로 작동하지 않을 것입니다:

-
// this.props.value가 { foo: 'bar' }라고 가정합니다
-// nextProps.value도 { foo: 'bar' }라고 가정하지만,
-// 이 참조는 this.props.value와 다른 것입니다
-this.props.value !== nextProps.value; // true
-
-

문제는 prop이 실제로 변경되지 않았을 때도 shouldComponentUpdatetrue를 반환할 거라는 겁니다. 이를 해결하기 위한 대안으로, 아래와 같이 구현해 볼 수 있습니다:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value.foo !== nextProps.value.foo;
-}
-
-

기본적으로, 우리는 변경을 정확히 추적하기 위해서 깊은 비교를 해야 했습니다. 이 방법은 성능 면에서 제법 비쌉니다. 각각의 모델마다 다른 깊은 등식 코드를 작성해야 하므로 확장이 힘들어 집니다. 심지어 객체 참조를 신중히 관리하지 않는다면 작동하지도 않을 수 있습니다. 컴포넌트가 부모에 의해 다뤄지는 경우를 살펴보죠:

-
React.createClass({
-  getInitialState: function() {
-    return { value: { foo: 'bar' } };
-  },
-
-  onClick: function() {
-    var value = this.state.value;
-    value.foo += 'bar'; // 안티패턴 입니다!
-    this.setState({ value: value });
-  },
-
-  render: function() {
-    return (
-      <div>
-        <InnerComponent value={this.state.value} />
-        <a onClick={this.onClick}>클릭하세요</a>
-      </div>
-    );
-  }
-});
-
-

처음엔 내부 컴포넌트(<InnerComponent />)가 { foo: 'bar' }를 value prop으로 가진 채 렌더될 것입니다. 사용자가 앵커(<a>)를 클릭한다면 부모 컴포넌트의 state는 { value: { foo: 'barbar' } }로 업데이트되고, 내부 컴포넌트 또한 { foo: 'barbar' }를 새로운 value prop으로 전달받아 다시 렌더링 되는 프로세스가 일어날 것입니다.

- -

이 문제는 부모와 내부 컴포넌트가 같은 객체에 대한 참조를 공유하기 때문에 발생합니다. onClick 함수의 두 번째 줄에서 객체에 대한 변경이 일어날 때, 내부 컴포넌트의 prop도 변경될 것입니다. 따라서 다시 렌더링 되는 프로세스가 시작될 때 shouldComponentUpdate가 호출되고 this.props.value.foonextProps.value.foo와 같게 됩니다. 실제로 this.props.valuenextProps.value와 같은 객체이기 때문입니다.

- -

그에따라 prop의 변경을 놓치게 되어 다시 렌더링하는 프로세스가 중단되고, UI는 'bar'에서 'barbar'로 업데이트되지 않습니다.

-

구원자 Immutable-js #

-

Immutable-js는 Lee Byron이 만들고 Facebook이 오픈소스화 한 JavaScript 컬렉션 라이브러리입니다. 이는 구조의 공유(structural sharing)를 통해 불변의 영속적인(immutable persistent) 컬렉션을 제공합니다. 이러한 속성이 무엇을 의미하는지 살펴보죠:

- -
    -
  • 불변성(Immutable): 컬렉션이 한번 생성되면, 이 후 다른 시점에 변경될 수 없습니다.
  • -
  • 영속성(Persistent): 새로운 컬렉션이 이전의 컬렉션이나 셋(set) 같은 뮤테이션(mutation)에서 생성될 수 있습니다. 기존의 컬렉션은 새로운 컬렉션이 생성된 후에도 여전히 유효합니다.
  • -
  • 구조의 공유(Structural Sharing): 새로운 컬렉션은 가능한 한 원래의 컬렉션과 같은 구조를 사용해 생성됩니다. 공간 효율성과 적절한 성능을 위해 복사를 최소화합니다.
  • -
- -

불변성은 변경의 추적을 비용을 줄여줍니다; 변경은 항상 새로운 객체에만 발생하기 때문에 객체에 대한 참조가 변경될 때만 확인하면 됩니다. 예를 들어 일반적인 이 JavaScript 코드에서는:

-
var x = { foo: "bar" };
-var y = x;
-y.foo = "baz";
-x === y; // true
-
-

y가 수정되더라도 여전히 같은 객체인 x를 참조하고 있기 때문에, 이 비교는 true를 반환합니다. 하지만 이 코드를 immutable-js를 사용해 다음과 같이 작성할 수 있습니다:

-
var SomeRecord = Immutable.Record({ foo: null });
-var x = new SomeRecord({ foo: 'bar' });
-var y = x.set('foo', 'baz');
-x === y; // false
-
-

이 경우, x가 변경되면 새로운 참조가 반환되기 때문에, 우리는 안전하게 x가 변경되었을 것으로 추정할 수 있습니다.

- -

변경을 탐지할 수 있는 또 다른 방법은 세터(setter)에 의해 설정된 플래그를 더티 체킹(dirty checking)하는 것입니다. 이 방식의 문제는 당신이 세터를 사용할 뿐만 아니라 수많은 추가 코드를 작성하거나 어떻게든 클래스들을 인스트루먼트(instrument) 하도록 강요한다는 것입니다. 혹은 변경(mutations) 직전에 객체를 깊은 복사(deep copy) 한 뒤 깊은 비교(deep compare)를 수행해 변경 여부를 판단할 수 있습니다. 이 방식의 문제점은 deepCopy와 deepCompare 둘 다 비용이 많이 드는 연산이라는 것입니다.

- -

그래서 Immutable 자료구조는 shouldComponentUpdate의 구현에 필요한 객체의 변경사항을 추적할 수 있는 덜 자세하지만 저렴한 방법을 제공합니다. 그에 따라 immutable-js가 제공하는 추상화를 사용해 props와 state 어트리뷰트를 모델링한다면, PureRenderMixin을 사용해 성능을 향상할 수 있습니다.

-

Immutable-js와 Flux #

-

Flux를 사용한다면 immutable-js를 사용해 stores를 작성해야 합니다. 전체 API를 살펴보세요.

- -

Immutable 자료구조를 이용해 스레드를 모델링하는 예제를 살펴봅시다. 먼저 모델링하려는 엔티티마다 Record를 정의해야 합니다. Record는 특정 필드들의 값을 유지하기 위한 불변의 컨테이너입니다:

-
var User = Immutable.Record({
-  id: undefined,
-  name: undefined,
-  email: undefined
-});
-
-var Message = Immutable.Record({
-  timestamp: new Date(),
-  sender: undefined,
-  text: ''
-});
-
-

Record 함수는 필드별로 기본값이 선언된 객체에 대한 정의를 넘겨받습니다.

- -

메시지 store는 두 개의 List를 통해 users와 messages를 추적할 수 있습니다:

-
this.users = Immutable.List();
-this.messages = Immutable.List();
-
-

각각의 페이로드 타입을 처리하는 기능을 구현하는 것은 꽤 간단합니다. 예를 들면, store가 새 메시지를 나타내는 페이로드를 확인할 때 레코드를 새로 생성하고 메시지 리스트에 추가할 수 있습니다.

-
this.messages = this.messages.push(new Message({
-  timestamp: payload.timestamp,
-  sender: payload.sender,
-  text: payload.text
-});
-
-

자료구조가 불변이기 때문에 push 함수의 결과를 this.messages에 할당할 필요가 있으니 주의하세요.

- -

React 측에서는, 컴포넌트의 state를 보존하기 위해 immutable-js 자료구조를 사용한다면, 모든 컴포넌트에 PureRenderMixin을 혼합해 다시 렌더링하는 프로세스를 중단할 수 있습니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/advanced-performance-zh-CN.html b/docs/advanced-performance-zh-CN.html deleted file mode 100644 index d3ae106119..0000000000 --- a/docs/advanced-performance-zh-CN.html +++ /dev/null @@ -1,654 +0,0 @@ - - - - - - - 提高性能 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 提高性能 -

-
- -

当人们考虑将React应用到自己的系统里时,都会想知道React是否可以和非React的应用一样可以快速的响应各种用户的操作。改变组件的state时,它会重新渲染组件的所有子节点,有人会怀疑这种重新渲染会带来很大的性能开销。但是React使用很多技术来最小化的减少DOM操作的开销达到更新UI的效果。

-

使用生产构建版本 #

-

如果你在开发React应用中,遇到了一些性能上的问题,你可以使用了minified production build进行测试。这个开发构建版本包括了额外的一些警告信息,可以帮助你更好的调试你的应用。由于它做了很多额外的开销,所以它运行起来会相对要慢一点。

-

避免调整真实DOM树 #

-

React利用虚拟DOM,来描述在浏览器上显示的真实DOM树。这种并行的表示方法,可以让React避免直接去操作DOM节点,毕竟操作DOM节点的开销要远远大于直接去操作Javascript的对象。当组件的state或者props更新的时候,React会根据新生成的虚拟DOM和之前的虚拟DOM进行比较,来判断是否需要去更新真实DOM上的内容。只有在前后虚拟DOM不相等的情况下,React才会去调整真实DOM的结构。

- -

在此之上,React提供了一个组件生命周期函数shouldComponentUpdate,它会在组件进行重渲染过程开始的时候(虚拟DOM和真实DOM进行对比)进行调用。让开发者可以短接这个过程。该函数默认会返回true,让React去执行更新。

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return true;
-}
-
-

记住一点,在React中,这个函数调用的非常频繁,所以里面的操作不能太复杂,一定要快。

- -

你有几个聊天对话的消息应用程序。假设只有一个对话改变了。如果你在ChatThread组件中实现了shouldComponentUpdate函数,React可以跳过对其他线程的重渲染的步骤。

-
shouldComponentUpdate: function(nextProps, nextState) {
-  // TODO: return whether or not current chat thread is
-  // different to former one.
-}
-
-

所以,总而言之,React可以让开发者使用shouldComponentUpdate函数来减少对DOM子树的调整,对于那些需要更新的组件,再进行虚拟DOMs的对比。

-

shouldComponentUpdate 实战 #

-

这个一个组件的子树的结构。每一个节点表示shouldComponentUpdate return了什么,以及是否虚拟DOMs是相等的。最后,圆的颜色代表这个节点是否需要被重新调整。

- -
- -

在上述例子中,C2节点的shouldComponentUpdate函数返回了false,所以React就不需要在这里产生新的虚拟DOM,也就不需要重新调整DOM。由于父节点C2已经在shouldComponentUpdate函数中返回false,所以它的所有子节点也就不会执行该函数。

- -

对于C1和C3,shouldComponentUpdate函数返回了true,React会从上往下对子节点进行检查。对于C6节点,它返回了true;由于前后的虚拟DOMs不相等,所以它不得不调整真实DOM。最后在C8这个有趣的节点上。React会去对比前后虚拟DOM,由于前后是相等的,所以它不是对真实DOM进行调整。

- -

请注意,React只会对C6进行DOM操作。对于C8,它通过对比虚拟DOMs的方式,避免重新渲染。对于C2的子节点以及C7,通过shouldComponentUpdate函数,直接忽略了虚拟DOM比较的过程,提高性能。

- -

所以,我们应该怎么样来实现shouldComponentUpdate方法?举个例子,你有个组件仅仅只渲染一个string的文案:

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.string.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value}</div>;
-  }
-});
-
-

我们可以简单的像下面一样实现shouldComponentUpdate

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value !== nextProps.value;
-}
-
-

目前为止,在props/state上处理简单的的数据结构是非常容易的。基于这种数据类型,我们可以通过mixin的方式把该函数引入到你的所有组件中去。事实上,React官方已经提供了这种方法:PureRenderMixin

- -

但是,如果你的组件使用的在state或者props上使用的是可变的数据结构怎么办?组件里的prop不是以一个string的形式'bar'存在,而是以一种Javascript对象的形式包含了一个字符串,类似这样{ foo: 'bar' }:

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.object.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value.foo}</div>;
-  }
-});
-
-

如果是这种情况,按照我们刚才的在shouldComponentUpdate的实现的话,是不能达到我们的预期:

-
// assume this.props.value is { foo: 'bar' }
-// assume nextProps.value is { foo: 'bar' },
-// but this reference is different to this.props.value
-this.props.value !== nextProps.value; // true
-
-

因为props实际上是没有改变的,所以shouldComponentUpdate始终会返回true。为了解决这个问题,我们也有一个可选的解决方案:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value.foo !== nextProps.value.foo;
-}
-
-

基本上,我们是不会利用这种深度比较去判断是否有属性改变。这样的操作十分损耗性能的,并且非常难扩展。最重要的是,如果我们没有仔细管理对象的引用关系,很可能导致对比不出结果。让我们来看看下面这个组件:

-
React.createClass({
-  getInitialState: function() {
-    return { value: { foo: 'bar' } };
-  },
-
-  onClick: function() {
-    var value = this.state.value;
-    value.foo += 'bar'; // ANTI-PATTERN!
-    this.setState({ value: value });
-  },
-
-  render: function() {
-    return (
-      <div>
-        <InnerComponent value={this.state.value} />
-        <a onClick={this.onClick}>Click me</a>
-      </div>
-    );
-  }
-});
-
-

子组件第一次渲染的时候,组件会收到{ foo: 'bar' }作为prop中的value的值。如果用户进行了点击的操作,父组件为更新state,变为{ value: { foo: 'barbar' } },之后会触发子组件的重渲染的过程,子组件会收到新的prop中value的值{ foo: 'barbar' }

- -

问题在与,因为父子组件共同分享了一个对象的引用,当这个对象在onClick函数中进行修改后,子组件的prop也已经改变。所以,当重渲染的过程开始,shouldComponentUpdate函数就会被触发,this.props.value.foonextProps.value.foo会是相等的。因为this.props.valuenextProps.value指向的是同一个对象。

- -

因此,我们直接阻止了子组件进行重新渲染,整个UI也就不会把'bar'更新为'barbar'

-

使用Immutable-js #

-

Immutable-js是一个由Lee Byron编写的Javascript的数据类型库,现在已经被Facebook开源了。它通过 结构共享 的方式提供了一个 持久不可变的 的集合。让我们来看看这个到底是什么东西。

- -
    -
  • 不可变:一旦被创建,一个集合不能被其他内容所改变
  • -
  • 持久性:新的集合可以由之前的集合创建出来,或者由一个可变的数据创建。当新的集合被创建出来,原始的集合依然有效。
  • -
  • 结构共享:新的集合会尽可能的复用之前集合内的内容。减少重复复制来提高性能。如果新集合和原来的集合是相等的,则会直接把之前的集合返回给新集合。
  • -
- -

不可变的特性让跟踪变化变得简单;每次改变总是会产生新的一个对象,所以。我们只需要判断一下它们引用是否相同即可。举个例子,下面是常规的Javascript的写法:

-
var x = { foo: "bar" };
-var y = x;
-y.foo = "baz";
-x === y; // true
-
-

尽管y已经被更改了,但是它的引用还是和x是一致的。所以他们两个进行对比,始终会返回true。所以,这样的操作应该要用immutable-js来完成:

-
var SomeRecord = Immutable.Record({ foo: null });
-var x = new SomeRecord({ foo: 'bar'  });
-var y = x.set('foo', 'baz');
-x === y; // false
-
-

在这样的情况中,当我们改变了x里的内容,会返回给我们一个新的引用,我们可以安全地假定x已经改变。

- -

另一种来跟踪数据变化的方法,是通过 setter 来设置标识符来做脏检查 (dirty checking)。这种方法的问题在于它强迫你使用 setter;你需要多写很多额外代码或者跟踪分析 class 中的数据。另外一种方式是,你可以在更改一个对象之前对它进行一次深复制,之后再进行深比较,来判断这次操作是否造成了数据改变:这种方案的问题在于深复制与深比较都是很昂贵的操作。

- -

所以,Immutable的数据结构给你提供了一个很方便的方式去跟踪一个对象是否被修改了,我们只需要简单的实现shouldComponentUpdate即可。因此,如果我们的props和state模型使用了immutable-js方式,我们可以引入PureRenderMixin,从而提高我们的应用的性能。

-

Immutable-js 结合 Flux #

-

如果你正在使用Flux,你应该在你的stores里使用immutable-js。可以来看下full API

- -

让我们看看一种使用Immutable数据结构来处理的方式。首先,我们为每一个入口定义一个Record去处理模型。Record是一个保存各个字段的一个容器。

-
var User = Immutable.Record({
-  id: undefined,
-  name: undefined,
-  email: undefined
-});
-
-var Message = Immutable.Record({
-  timestamp: new Date(),
-  sender: undefined,
-  text: ''
-});
-
-

Record 函数接受一个对象作为参数;这个对象定义了 Record 中的键值与默认值

- -

store可以用两个list来记录users和messages

-
this.users = Immutable.List();
-this.messages = Immutable.List();
-
-

它可以很方便的实现处理payload数据类型。例如,当一个store收到了新的信息,我们可以直接创建一个新的record,然后把它加到我们message的list中去。

-
this.messages = this.messages.push(new Message({
-  timestamp: payload.timestamp,
-  sender: payload.sender,
-  text: payload.text
-});
-
-

注意,因为data的数据结构是不可变的,我们需要重新对this.message进行赋值。

- -

在React方面,如果我们用了 immutable-js的数据结构去保存组件的state,我们就可以引入PureRenderMixin到所有你的组件中,做一个快速的判断是否需要重新渲染的操作。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/advanced-performance.html b/docs/advanced-performance.html index 797bb040ff..83369d42e1 100644 --- a/docs/advanced-performance.html +++ b/docs/advanced-performance.html @@ -1,655 +1,10 @@ - - - - - - Advanced Performance | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Advanced Performance -

-
- -

One of the first questions people ask when considering React for a project is whether their application will be as fast and responsive as an equivalent non-React version. The idea of re-rendering an entire subtree of components in response to every state change makes people wonder whether this process negatively impacts performance. React uses several clever techniques to minimize the number of costly DOM operations required to update the UI.

-

Use the production build #

-

If you're benchmarking or experiencing performance problems in your React apps, make sure you're testing with the minified production build. The development build includes extra warnings that are helpful when building your apps, but it is slower due to the extra bookkeeping it does.

-

Avoiding reconciling the DOM #

-

React makes use of a virtual DOM, which is a descriptor of a DOM subtree rendered in the browser. This parallel representation allows React to avoid creating DOM nodes and accessing existing ones, which is slower than operations on JavaScript objects. When a component's props or state change, React decides whether an actual DOM update is necessary by constructing a new virtual DOM and comparing it to the old one. Only in the case they are not equal, will React reconcile the DOM, applying as few mutations as possible.

- -

On top of this, React provides a component lifecycle function, shouldComponentUpdate, which is triggered before the re-rendering process starts (virtual DOM comparison and possible eventual DOM reconciliation), giving the developer the ability to short circuit this process. The default implementation of this function returns true, leaving React to perform the update:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return true;
-}
-
-

Keep in mind that React will invoke this function pretty often, so the implementation has to be fast.

- -

Say you have a messaging application with several chat threads. Suppose only one of the threads has changed. If we implement shouldComponentUpdate on the ChatThread component, React can skip the rendering step for the other threads:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  // TODO: return whether or not current chat thread is
-  // different to former one.
-}
-
-

So, in summary, React avoids carrying out expensive DOM operations required to reconcile subtrees of the DOM by allowing the user to short circuit the process using shouldComponentUpdate, and, for those which should update, by comparing virtual DOMs.

-

shouldComponentUpdate in action #

-

Here's a subtree of components. For each one is indicated what shouldComponentUpdate returned and whether or not the virtual DOMs were equivalent. Finally, the circle's color indicates whether the component had to be reconciled or not.

- -
- -

In the example above, since shouldComponentUpdate returned false for the subtree rooted at C2, React had no need to generate the new virtual DOM, and therefore, it neither needed to reconcile the DOM. Note that React didn't even have to invoke shouldComponentUpdate on C4 and C5.

- -

For C1 and C3 shouldComponentUpdate returned true, so React had to go down to the leaves and check them. For C6 it returned true; since the virtual DOMs weren't equivalent it had to reconcile the DOM. -The last interesting case is C8. For this node React had to compute the virtual DOM, but since it was equal to the old one, it didn't have to reconcile it's DOM.

- -

Note that React only had to do DOM mutations for C6, which was inevitable. For C8, it bailed out by comparing the virtual DOMs, and for C2's subtree and C7, it didn't even have to compute the virtual DOM as we bailed out on shouldComponentUpdate.

- -

So, how should we implement shouldComponentUpdate? Say that you have a component that just renders a string value:

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.string.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value}</div>;
-  }
-});
-
-

We could easily implement shouldComponentUpdate as follows:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value !== nextProps.value;
-}
-
-

So far so good, dealing with such simple props/state structures is easy. We could even generalize an implementation based on shallow equality and mix it into components. In fact, React already provides such implementation: PureRenderMixin.

- -

But what if your components' props or state are mutable data structures? Say the prop the component receives, instead of being a string like 'bar', is a JavaScript object that contains a string such as, { foo: 'bar' }:

-
React.createClass({
-  propTypes: {
-    value: React.PropTypes.object.isRequired
-  },
-
-  render: function() {
-    return <div>{this.props.value.foo}</div>;
-  }
-});
-
-

The implementation of shouldComponentUpdate we had before wouldn't always work as expected:

-
// assume this.props.value is { foo: 'bar' }
-// assume nextProps.value is { foo: 'bar' },
-// but this reference is different to this.props.value
-this.props.value !== nextProps.value; // true
-
-

The problem is shouldComponentUpdate will return true when the prop actually didn't change. To fix this, we could come up with this alternative implementation:

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return this.props.value.foo !== nextProps.value.foo;
-}
-
-

Basically, we ended up doing a deep comparison to make sure we properly track changes. In terms of performance, this approach is pretty expensive. It doesn't scale as we would have to write different deep equality code for each model. On top of that, it might not even work if we don't carefully manage object references. Say this component is used by a parent:

-
React.createClass({
-  getInitialState: function() {
-    return { value: { foo: 'bar' } };
-  },
-
-  onClick: function() {
-    var value = this.state.value;
-    value.foo += 'bar'; // ANTI-PATTERN!
-    this.setState({ value: value });
-  },
-
-  render: function() {
-    return (
-      <div>
-        <InnerComponent value={this.state.value} />
-        <a onClick={this.onClick}>Click me</a>
-      </div>
-    );
-  }
-});
-
-

The first time the inner component gets rendered, it will have { foo: 'bar' } as the value prop. If the user clicks on the anchor, the parent component's state will get updated to { value: { foo: 'barbar' } }, triggering the re-rendering process of the inner component, which will receive { foo: 'barbar' } as the new value for the prop.

- -

The problem is that since the parent and inner components share a reference to the same object, when the object gets mutated on line 2 of the onClick function, the prop the inner component had will change. So, when the re-rendering process starts, and shouldComponentUpdate gets invoked, this.props.value.foo will be equal to nextProps.value.foo, because in fact, this.props.value references the same object as nextProps.value.

- -

Consequently, since we'll miss the change on the prop and short circuit the re-rendering process, the UI won't get updated from 'bar' to 'barbar'.

-

Immutable-js to the rescue #

-

Immutable-js is a JavaScript collections library written by Lee Byron, which Facebook recently open-sourced. It provides immutable persistent collections via structural sharing. Let's see what these properties mean:

- -
    -
  • Immutable: once created, a collection cannot be altered at another point in time.
  • -
  • Persistent: new collections can be created from a previous collection and a mutation such as set. The original collection is still valid after the new collection is created.
  • -
  • Structural Sharing: new collections are created using as much of the same structure as the original collection as possible, reducing copying to a minimum to achieve space efficiency and acceptable performance. If the new collection is equal to the original, the original is often returned.
  • -
- -

Immutability makes tracking changes cheap; a change will always result in a new object so we only need to check if the reference to the object has changed. For example, in this regular JavaScript code:

-
var x = { foo: "bar" };
-var y = x;
-y.foo = "baz";
-x === y; // true
-
-

Although y was edited, since it's a reference to the same object as x, this comparison returns true. However, this code could be written using immutable-js as follows:

-
var SomeRecord = Immutable.Record({ foo: null });
-var x = new SomeRecord({ foo: 'bar'  });
-var y = x.set('foo', 'baz');
-x === y; // false
-
-

In this case, since a new reference is returned when mutating x, we can safely assume that x has changed.

- -

Another possible way to track changes could be doing dirty checking by having a flag set by setters. A problem with this approach is that it forces you to use setters and, either write a lot of additional code, or somehow instrument your classes. Alternatively, you could deep copy the object just before the mutations and deep compare to determine whether there was a change or not. A problem with this approach is both deepCopy and deepCompare are expensive operations.

- -

So, Immutable data structures provides you a cheap and less verbose way to track changes on objects, which is all we need to implement shouldComponentUpdate. Therefore, if we model props and state attributes using the abstractions provided by immutable-js we'll be able to use PureRenderMixin and get a nice boost in perf.

-

Immutable-js and Flux #

-

If you're using Flux, you should start writing your stores using immutable-js. Take a look at the full API.

- -

Let's see one possible way to model the thread example using Immutable data structures. First, we need to define a Record for each of the entities we're trying to model. Records are just immutable containers that hold values for a specific set of fields:

-
var User = Immutable.Record({
-  id: undefined,
-  name: undefined,
-  email: undefined
-});
-
-var Message = Immutable.Record({
-  timestamp: new Date(),
-  sender: undefined,
-  text: ''
-});
-
-

The Record function receives an object that defines the fields the object has and its default values.

- -

The messages store could keep track of the users and messages using two lists:

-
this.users = Immutable.List();
-this.messages = Immutable.List();
-
-

It should be pretty straightforward to implement functions to process each payload type. For instance, when the store sees a payload representing a new message, we can just create a new record and append it to the messages list:

-
this.messages = this.messages.push(new Message({
-  timestamp: payload.timestamp,
-  sender: payload.sender,
-  text: payload.text
-});
-
-

Note that since the data structures are immutable, we need to assign the result of the push function to this.messages.

- -

On the React side, if we also use immutable-js data structures to hold the components' state, we could mix PureRenderMixin into all our components and short circuit the re-rendering process.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/animation-it-IT.html b/docs/animation-it-IT.html deleted file mode 100644 index 5b1811cecc..0000000000 --- a/docs/animation-it-IT.html +++ /dev/null @@ -1,703 +0,0 @@ - - - - - - - Animazioni | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Animazioni -

-
- -

React offre un componente addon ReactTransitionGroup come una API di basso livello per le animazioni, e un ReactCSSTransitionGroup per implementare facilmente animazioni e transizioni CSS di base.

-

API di Alto Livello: ReactCSSTransitionGroup #

-

ReactCSSTransitionGroup è basato su ReactTransitionGroup ed è una maniera semplice di effettuare transizioni e animazioni CSS quando un componente React viene aggiunto o rimosso dal DOM. È ispirato all'eccellente libreria ng-animate.

-

Per Cominciare #

-

ReactCSSTransitionGroup è l'interfaccia a ReactTransitions. Questo è un semplice elemento che racchiude tutti i componenti che desideri animare. Ecco un esempio in cui facciamo apparire e scomparire gli elementi di una lista.

-
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
-
-var TodoList = React.createClass({
-  getInitialState: function() {
-    return {items: ['ciao', 'mondo', 'clicca', 'qui']};
-  },
-  handleAdd: function() {
-    var newItems =
-      this.state.items.concat([prompt('Scrivi del testo')]);
-    this.setState({items: newItems});
-  },
-  handleRemove: function(i) {
-    var newItems = this.state.items;
-    newItems.splice(i, 1);
-    this.setState({items: newItems});
-  },
-  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          {item}
-        </div>
-      );
-    }.bind(this));
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Aggiungi Elemento</button>
-        <ReactCSSTransitionGroup 
-          transitionName="example" 
-          transitionEnterTimeout={500} 
-          transitionLeaveTimeout={300}>
-          {items}
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-
-
-

Nota:

- -

Devi fornire l'attributo key per tutti i figli di ReactCSSTransitionGroup, anche quando stai visualizzando un singolo elemento. Questo è il modo in cui React determina quali figli sono stati aggiunti, rimossi, o sono rimasti.

-
- -

In questo componente, quando un nuovo elemento viene aggiunto a ReactCSSTransitionGroup riceverà la classe CSS example-enter e la classe CSS example-enter-active allo scatto successivo. Questa è una convenzione basata sul valore della proprietà transitionName.

- -

Puoi usare queste classi per scatenare una animazione o transizione CSS. Ad esempio, prova ad aggiungere questo CSS e aggiungere un nuovo elemento alla lista:

-
.example-enter {
-  opacity: 0.01;
-}
-
-.example-enter.example-enter-active {
-  opacity: 1;
-  transition: opacity 500ms ease-in;
-}
-
-.example-leave {
-  opacity: 1;
-}
-
-.example-leave.example-leave-active {
-  opacity: 0.01;
-  transition: opacity 300ms ease-in;
-}
-
-

Ti accorgerai che la durata delle animazioni devono essere specificate sia nel CSS che nel metodo render; questo suggerisce a React quando rimuovere le classi di animazione dall'elemento e -- se sta venendo rimosso -- quando rimuovere l'elemento dal DOM.

-

Animare il Montaggio Iniziale #

-

ReactCSSTransitionGroup fornisce la proprietà opzionale transitionAppear, per aggiungere una fase aggiuntiva di transizione al montaggio iniziale del componente. In genere non c'è alcuna fase di transizione al montaggio iniziale in quanto il valore predefinito di transitionAppear è false. L'esempio seguente passa la proprietà transitionAppear con il valore true.

-
  render: function() {
-    return (
-      <ReactCSSTransitionGroup 
-        transitionName="example" 
-        transitionAppear={true} 
-        transitionAppearTimeout={500}>
-        <h1>Dissolvenza al Montaggio Iniziale</h1>
-      </ReactCSSTransitionGroup>
-    );
-  }
-
-

Durante il montaggio iniziale ReactCSSTransitionGroup otterrà la classe CSS example-appear e la classe CSS example-appear-active allo scatto successivo.

-
.example-appear {
-  opacity: 0.01;
-}
-
-.example-appear.example-appear-active {
-  opacity: 1;
-  transition: opacity .5s ease-in;
-}
-
-

Al montaggio iniziale, tutti i figli di ReactCSSTransitionGroup saranno marcati come appear ma non enter. Tuttavia, tutti i figli aggiunti in seguito ad un ReactCSSTransitionGroup esistente saranno marcati come enter ma non appear.

- -
-

Nota:

- -

La proprietà transitionAppear è stata aggiunta a ReactCSSTransitionGroup nella versione 0.13. Per mantenere la compatibilità con le versioni precedenti, il valore predefinito è impostato a false.

-
-

Classi Personalizzate #

-

È anche possibile usare nomi di classi personalizzate per ciascuna delle fasi delle tue transizioni. Anziché passare una stringa come valore di transitionName puoi assegnare un oggetto che contiene i nomi delle classi enter o leave, oppure un oggetto contenente i nomi delle classi per enter, enter-active, leave-activee leave. Se vengono forniti soltanto i nomi delle classi enter e leave, le classi per enter-active e leave-active saranno determinate aggiungendo il suffisso '-active' ai rispettivi nomi delle classi. Ecco due esempi che usano le classi personalizzate:

-
  ...
-  <ReactCSSTransitionGroup
-    transitionName={ {
-      enter: 'enter',
-      enterActive: 'enterActive',
-      leave: 'leave',
-      leaveActive: 'leaveActive',
-      appear: 'appear',
-      appearActive: 'appearActive'
-    } }>
-    {item}
-  </ReactCSSTransitionGroup>
-
-  <ReactCSSTransitionGroup
-    transitionName={ {
-      enter: 'enter',
-      leave: 'leave',
-      appear: 'appear'
-    } }>
-    {item2}
-  </ReactCSSTransitionGroup>
-  ...
-

I Gruppi di Animazioni Devono Essere Montati per Funzionare #

-

Per applicare le transizioni ai suoi figli, il ReactCSSTransitionGroup deve già essere montato nel DOM oppure la proprietà transitionAppear deve essere impostata a true. L'esempio seguente non funziona, poiché ReactCSSTransitionGroup sta venendo montato assieme al nuovo elemento, anziché il nuovo elemento venire montato dentro di esso. Confronta questo esempio con la sezione precedente Per Cominciare per notare la differenza.

-
  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          <ReactCSSTransitionGroup transitionName="example">
-            {item}
-          </ReactCSSTransitionGroup>
-        </div>
-      );
-    }, this);
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Aggiungi Elemento</button>
-        {items}
-      </div>
-    );
-  }
-

Animare Uno o Nessun Elemento #

-

Nell'esempio precedente, abbiamo visualizzato una lista di elementi in ReactCSSTransitionGroup. Tuttavia, i figli di ReactCSSTransitionGroup possono anche essere un solo o nessun elemento. Questo rende possibile animare un singolo elemento che viene aggiunto o rimosso. Similarmente, puoi animare un nuovo elemento che sistituisce l'elemento corrente. Ad esempio, possiamo implementare un semplice carosello di immagini come segue:

-
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
-
-var ImageCarousel = React.createClass({
-  propTypes: {
-    imageSrc: React.PropTypes.string.isRequired
-  },
-  render: function() {
-    return (
-      <div>
-        <ReactCSSTransitionGroup 
-          transitionName="carousel" 
-          transitionEnterTimeout={300} 
-          transitionLeaveTimeout={300}>
-          <img src={this.props.imageSrc} key={this.props.imageSrc} />
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-

Disattivare le Animazioni #

-

Se lo desideri, puoi disattivare le animazioni enter o leave. Ad esempio, a volte potresti volere un'animazione per enter ma non una per leave, ma ReactCSSTransitionGroup attende che l'animazione sia completata prima di rimuovere il tuo nodo DOM. Puoi aggiungere le proprietà transitionEnter={false} o transitionLeave={false} a ReactCSSTransitionGroup per disattivare le rispettive animazioni.

- -
-

Nota:

- -

Quando si usa ReactCSSTransitionGroup, non c'è alcun modo per cui i tuoi componenti vengano avvisati quando la transizione è terminata o per effettuare una logica complessa durante l'animazione. Se vuoi un controllo più fine, puoi usare la API di basso livello ReactTransitionGroup che fornisce degli hook che puoi utilizzare per effettuare transizioni personalizzate.

-
-

API di Basso Livello: ReactTransitionGroup #

-

ReactTransitionGroup è la base per le animazioni. È accessibile come React.addons.TransitionGroup. Quando vi sono aggiunti o rimossi dichiarativamente dei figli (come negli esempi precedenti) degli speciali hook del ciclo di vita sono invocati su di essi.

-

componentWillAppear(callback) #

-

Viene chiamato allo stesso momento di componentDidMount() per i componenti inizialmente montati in un TransitionGroup. Bloccherà l'esecuzione di altre animazioni finché callback non viene chiamata. Viene chiamata solo durante il rendering iniziale di un TransitionGroup.

-

componentDidAppear() #

-

Viene chiamato dopo che la funzione callback passata a componentWillAppear è stata chiamata.

-

componentWillEnter(callback) #

-

Viene chiamato allo stesso momento di componentDidMount() per i componenti aggiunti ad un TransitionGroup esistente. Bloccherà l'esecuzione di altre animazioni finché callback non viene chiamata. Non viene chiamata durante il rendering iniziale di un TransitionGroup.

-

componentDidEnter() #

-

Viene chiamato dopo che la funzione callback passata a componentWillEnter è stata chiamata.

-

componentWillLeave(callback) #

-

Viene chiamato quando il figlio è stato rimosso dal ReactTransitionGroup. Nonostante il figlio sia stato rimosso, ReactTransitionGroup lo manterrà nel DOM finché callback non viene chiamata.

-

componentDidLeave() #

-

Viene chiamato quando la callback willLeave viene chiamata (contemporaneamente a componentWillUnmount).

-

Rendering di un Componente Diverso #

-

In maniera predefinita, ReactTransitionGroup viene visualizzato come uno span. Puoi cambiare questo comportamento fornento una proprietà component. Ad esempio, ecco come puoi visualizzare un <ul>:

-
<ReactTransitionGroup component="ul">
-  ...
-</ReactTransitionGroup>
-
-

È possibile utilizzare ciascun componente DOM che React può visualizzare. Tuttavia, component non deve necessariamente essere un componente DOM. Può infatti essere qualunque componente React; anche componenti scritti da te!

- -
-

Nota:

- -

Prima della v0.12, quando venivano usati componenti DOM, la proprietà component doveva essere un riferimento a React.DOM.*. Dal momento che il componente è semplicemente passato a React.createElement, deve ora essere una stringa. Per componenti compositi si deve passare il metodo factory.

-
- -

Ciascuna proprietà aggiuntiva definita dall'utente diverrà una proprietà del componente visualizzato. Ad esempio, ecco come visualizzeresti un <ul> con una classe CSS:

-
<ReactTransitionGroup component="ul" className="animated-list">
-  ...
-</ReactTransitionGroup>
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/animation-ja-JP.html b/docs/animation-ja-JP.html deleted file mode 100644 index afd1782c6f..0000000000 --- a/docs/animation-ja-JP.html +++ /dev/null @@ -1,674 +0,0 @@ - - - - - - - アニメーション | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- アニメーション -

-
- -

ReactはアニメーションのためにローレベルAPIとして ReactTransitionGroup アドオンコンポーネントと、基本的なCSSアニメーションとトランジションを簡単に実行するために ReactCSSTransitionGroup を提供しています。

-

ハイレベルAPI: ReactCSSTransitionGroup #

-

ReactCSSTransitionGroupReactTransitionGroup に基づいており、ReactコンポーネントがDOMを作成したり、削除したりする際に、CSSのトランジションとアニメーションを行う簡単な方法です。これは、素晴らしいng-animateライブラリにインスパイアされています。

-

はじめに #

-

ReactCSSTransitionGroupReactTransitions のインターフェースです。アニメーションに関心がある全てのコンポーネントをラップする単純な要素です。以下が、リストのアイテムをフェードインやフェードアウトさせる例です。

-
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
-
-var TodoList = React.createClass({
-  getInitialState: function() {
-    return {items: ['hello', 'world', 'click', 'me']};
-  },
-  handleAdd: function() {
-    var newItems =
-      this.state.items.concat([prompt('Enter some text')]);
-    this.setState({items: newItems});
-  },
-  handleRemove: function(i) {
-    var newItems = this.state.items;
-    newItems.splice(i, 1);
-    this.setState({items: newItems});
-  },
-  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          {item}
-        </div>
-      );
-    }.bind(this));
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Add Item</button>
-        <ReactCSSTransitionGroup 
-          transitionName="example" 
-          transitionEnterTimeout={500} 
-          transitionLeaveTimeout={300}>
-          {items}
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-
-
-

注意: -もし子要素を1つだけレンダリングするとしても、 ReactCSSTransitionGroup の全ての子要素に提供しなければなりません。これが、Reactが、子要素が作成されているか、削除されたか、あるいはそのままであるか判断する方法です。

-
- -

このコンポーネントでは、 ReactCSSTransitionGroup に新しいアイテムが追加された次の瞬間に、 example-enter CSSクラスと example-enter-active CSSクラスを得ます。これは、 transitionName propに基づく習慣です。

- -

これらのクラスはCSSアニメーションやトランジションのトリガーとして使うことができます。例えば、以下のようにして、このCSSを加え、新しいリストアイテムを加えてみましょう。

-
.example-enter {
-  opacity: 0.01;
-  transition: opacity .5s ease-in;
-}
-
-.example-enter.example-enter-active {
-  opacity: 1;
-}
-
-

アイテムを削除しようとしたときに、 ReactCSSTransitionGroup がDOMの中にそれを保持していることに気づくでしょう。縮小化されていないReactのビルドとアドオンを使っているならば、Reactがアニメーションやトランジションが起こることを予期しているという警告が出るでしょう。これは、 ReactCSSTransitionGroup がアニメーションが終わるまでDOM要素をページに保持し続けるからです。以下のCSSを加えてみましょう。

-
.example-leave {
-  opacity: 1;
-  transition: opacity .5s ease-in;
-}
-
-.example-leave.example-leave-active {
-  opacity: 0.01;
-}
-

最初のマウントにおけるアニメーション #

-

ReactCSSTransitionGrouptransitionAppear というオプションのプロパティを提供します。コンポーネントの最初のマウントの際に、更なるトランジションのフェーズを加えるためです。一般的には、 transitionAppearfalse である最初のマウントの際にはトランジションのフェーズはありません。 transitionAppear プロパティを値が true である状態で渡す以下の例を見てみましょう。

-
  render: function() {
-    return (
-      <ReactCSSTransitionGroup 
-        transitionName="example" 
-        transitionAppear={true} 
-        transitionAppearTimeout={500}>
-        <h1>Fading at Initial Mount</h1>
-      </ReactCSSTransitionGroup>
-    );
-  }
-
-

最初のマウントの間、 ReactCSSTransitionGroupexample-appear CSSクラスを得て、次の瞬間に example-appear-active CSSクラスを加えます。

-
.example-appear {
-  opacity: 0.01;
-  transition: opacity .5s ease-in;
-}
-
-.example-appear.example-appear-active {
-  opacity: 1;
-}
-
-

最初のマウントの際には、 ReactCSSTransitionGroup の全ての子要素は appear しますが、 enter はしません。一方、存在する ReactCSSTransitionGroup に後から加えられた子要素は全て enter しますが、 appear はしません。

- -
-

注意: -transitionAppear プロパティはバージョン 0.13ReactCSSTransitionGroup に加えられました。後方互換性を維持するために、デフォルトの値は false に指定されています。

-
-

アニメーショングループを動かすためには、マウントされている必要があります #

-

子要素にトランジションを適用するためには、 ReactCSSTransitionGroup はすでにDOMにマウントされているか、 transitionAppear プロパティに true がセットされている必要があります。以下の例は動きません。 ReactCSSTransitionGroup が新しいアイテムとともにマウントされており、新しいマウントがマウントされていないからです。これと上のはじめに とで違いを比較してみてください。

-
  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          <ReactCSSTransitionGroup transitionName="example">
-            {item}
-          </ReactCSSTransitionGroup>
-        </div>
-      );
-    }, this);
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Add Item</button>
-        {items}
-      </div>
-    );
-  }
-

1個か0個のアイテムをアニメーションする #

-

上の例では、 ReactCSSTransitionGroup にアイテムのリストをレンダリングしました。しかし、 ReactCSSTransitionGroup の子要素は1個や0個のアイテムになり得ます。単一の要素が作成や削除のアニメーションを可能にします。同様に、現在の要素を置き換える新しい要素をアニメーションできます。例えば、以下のように、1つの画像でカルーセルを実行できます。

-
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
-
-var ImageCarousel = React.createClass({
-  propTypes: {
-    imageSrc: React.PropTypes.string.isRequired
-  },
-  render: function() {
-    return (
-      <div>
-        <ReactCSSTransitionGroup 
-          transitionName="carousel" 
-          transitionEnterTimeout={300} 
-          transitionLeaveTimeout={300}>
-          <img src={this.props.imageSrc} key={this.props.imageSrc} />
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-

アニメーションを作動させないようにする #

-

もししたいならば、 enterleave のアニメーションを無効にすることもできます。例えば、 enter アニメーションは行いたいが、 leave のアニメーションは行いたくない場合があるでしょう。しかし、 ReactCSSTransitionGroup はDOMのノードが削除される前にアニメーションが終わるのを待ちます。ReactCSSTransitionGroup がそれらのアニメーションを無効化するために、 transitionEnter={false}transitionLeave={false} といったプロパティを追加することができます。

- -
-

注意: -ReactCSSTransitionGroup を使う際には、コンポーネントがトランジションが終わったことを検知したり、アニメーション関連でさらに複雑なロジックを実行するといったことはできません。更に細かな制御を求める場合は、トランジションをカスタムするために必要なフックを提供するローレベルの ReactTransitionGroup APIを使用できます。

-
-

ローレベルAPI: ReactTransitionGroup #

-

ReactTransitionGroup はアニメーションの基盤です。 React.addons.TransitionGroup と同じくらい簡単に使用できます。これによって(上記の例のように)、宣言的に子要素が追加されたり削除されたりするときに、それらの上で特別なライフサイクルのフックが呼ばれます。

-

componentWillAppear(callback) #

-

このメソッドは TransitionGroup の中で最初にマウントされるコンポーネントのために componentDidMount() と同時に呼ばれます。これは、 callback が呼ばれるまで、他のアニメーションが発生するのをブロックします。これは、 TransitionGroup の最初のレンダリングのときにのみ呼ばれます。

-

componentDidAppear() #

-

componentWillAppear が呼ばれて渡される callback 関数の後に呼ばれます。

-

componentWillEnter(callback) #

-

これは、存在する TransitionGroup に追加されるコンポーネントのために、 componentDidMount() と同時に呼ばれます。これは、 callback が呼ばれるまで、他のアニメーションが発生するのをブロックします。これは、 TransitionGroup の最初のレンダリングのときには呼ばれません。

-

componentDidEnter() #

-

componentWillEnter が呼ばれて渡される callback 関数の後に呼ばれます。

-

componentWillLeave(callback) #

-

これは、 ReactTransitionGroup から子要素が削除されたときに呼ばれます。子要素が削除されても、 ReactTransitionGroupcallback が呼ばれるまでDOMの中に子要素を保持し続けます。

-

componentDidLeave() #

-

これは、 willLeavecallback が呼ばれた際に呼ばれます( componentWillUnmount と同時です)。

-

異なるコンポーネントをレンダリングする #

-

デフォルトで、 ReactTransitionGroupspan としてレンダリングされます。この動きは、 component プロパティによって変更できます。例えば、 <ul> をレンダリングしたい場合は以下のようになります。

-
<ReactTransitionGroup component="ul">
-  ...
-</ReactTransitionGroup>
-
-

Reactがレンダリングできる全てのDOMコンポーネントが使用できます。しかし、 component はDOMコンポーネントである必要はありません。あなたが求めているどんなReactのコンポーネントにもなり得ます。あなた自身が記述したものにもです!

- -
-

注意: -v0.12以前では、DOMのコンポーネントを使用する際には、 component プロパティが React.DOM.* を参照している必要がありました。コンポーネントが単純に React.createElementから渡されていたからです。これは今は文字列である必要があります。複合的なコンポーネントは複合的なものを渡す必要があります。

-
- -

全ての付加的な、ユーザー定義のプロパティはレンダリングされたコンポーネントのプロパティになります。例えば、以下はCSSクラスとともに <ul> をレンダリングする方法です。

-
<ReactTransitionGroup component="ul" className="animated-list">
-  ...
-</ReactTransitionGroup>
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/animation-ko-KR.html b/docs/animation-ko-KR.html deleted file mode 100644 index 4308f24f87..0000000000 --- a/docs/animation-ko-KR.html +++ /dev/null @@ -1,697 +0,0 @@ - - - - - - - 애니메이션 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 애니메이션 -

-
- -

React에는 애니메이션을 위한 저 수준 API로 ReactTransitionGroup 애드온 컴포넌트가 있고 간단히 기초 CSS 애니메이션과 트랜지션을 구현할 수 있는 ReactCSSTransitionGroup가 있습니다.

-

고 레벨 API: ReactCSSTransitionGroup #

-

ReactCSSTransitionGroupReactTransitionGroup를 기반으로 React 컴포넌트가 DOM에 들어가거나 나올때의 CSS의 트랜지션과 애니메이션을 구현하기 쉽게합니다. 이는 ng-animate 라이브러리에 영향을 받았습니다.

-

시작하기 #

-

ReactCSSTransitionGroupReactTransitions을 위한 인터페이스입니다. 이는 애니메이션을 제어할 모든 컴포넌트를 감싸는 하나의 엘리먼트 입니다. 아래는 목록의 아이템을 페이드 인/아웃하는 간단한 예제입니다.

-
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
-
-var TodoList = React.createClass({
-  getInitialState: function() {
-    return {items: ['hello', 'world', 'click', 'me']};
-  },
-  handleAdd: function() {
-    var newItems =
-      this.state.items.concat([prompt('Enter some text')]);
-    this.setState({items: newItems});
-  },
-  handleRemove: function(i) {
-    var newItems = this.state.items;
-    newItems.splice(i, 1);
-    this.setState({items: newItems});
-  },
-  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          {item}
-        </div>
-      );
-    }.bind(this));
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Add Item</button>
-        <ReactCSSTransitionGroup 
-          transitionName="example" 
-          transitionEnterTimeout={500} 
-          transitionLeaveTimeout={300}>
-          {items}
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-
-
-

주의:

- -

ReactCSSTransitionGroup의 모든 자식은 key 어트리뷰트를 반드시 만들어야 합니다. 한 아이템을 렌더할 때도 예외는 아닙니다. 키는 React가 어떤 자식이 들어오고, 나가고, 머무르는지 파악할 때 사용합니다.

-
- -

이 컴포넌트에서 새로운 아이템이 ReactCSSTransitionGroup에 추가되면 example-enter 아이템은 CSS 클래스를 가지게 되고 다음 순간에 example-enter-active CSS 클래스가 추가됩니다. 이는 transitionName prop을 기반으로 한 관례입니다.

- -

이 클래스들은 CSS 애니메이션이나 트랜지션을 일으키는데 사용할 수 있습니다. 예를 들어, 이 CSS를 넣은 후 아이템을 추가해 보세요.

-
.example-enter {
-  opacity: 0.01;
-}
-
-.example-enter.example-enter-active {
-  opacity: 1;
-  transition: opacity 500ms ease-in;
-}
-
-.example-leave {
-  opacity: 1;
-}
-
-.example-leave.example-leave-active {
-  opacity: 0.01;
-  transition: opacity 300ms ease-in;
-}
-
-

에니메이션 기간이 CSS와 렌더 메소드 양쪽에 지정될 필요가 있다는 것에 주의하셔야 합니다. 이는 엘리먼트에서 애니메이션 클래스를 제거할 때 (만약 남아있다면) DOM에서 엘리먼트를 제거할 때 React에 알려줍니다.

-

처음 마운트에서 애니메이션 하기 #

-

ReactCSSTransitionGroup은 컴포넌트를 처음 마운트할 때 추가 트렌지션 단계를 추가하기 위해, 선택적인 prop transitionAppear를 제공합니다. 일반적으로 처음 마운트할 때 트렌지션 단계를 넣지 않기 때문에 transitionAppear의 기본 값은 false입니다. 뒤의 예제는 transitionAppear prop에 true 값을 넘기고 있습니다.

-
  render: function() {
-    return (
-      <ReactCSSTransitionGroup 
-        transitionName="example" 
-        transitionAppear={true} 
-        transitionAppearTimeout={500}>
-        <h1>Fading at Initial Mount</h1>
-      </ReactCSSTransitionGroup>
-    );
-  }
-
-

처음 마운트할 때 ReactCSSTransitionGroupexample-appear CSS 클래스를 받고 그 다음에 example-appear-active CSS 클래스가 추가됩니다.

-
.example-appear {
-  opacity: 0.01;
-}
-
-.example-appear.example-appear-active {
-  opacity: 1;
-  transition: opacity .5s ease-in;
-}
-
-

처음 마운트할 때, ReactCSSTransitionGroup의 모든 자식은 appear하지만 enter하지 않습니다. 하지만, 존재하는 ReactCSSTransitionGroup에 추가되는 모든 자식은 enter하지만 appear하지 않습니다.

- -
-

주의:

- -

transitionAppear prop은 버전 0.13에서 ReactCSSTransitionGroup에 추가되었습니다. 하위 호환성을 생각해서, 기본 값은 false로 설정되어 있습니다.

-
-

커스텀 클래스 #

-

트렌지션의 각 단계에서 커스텀 클래스 이름을 사용할 수도 있습니다. transitionName에 문자열을 넘기는 대신 enter, leave 같은 클래스 이름의 객체나 enter, enter-active, leave-active, leave같은 클래스 이름의 객체를 넘길 수 있습니다. enter, leave 클래스만 있다면, enter-active, leave-active 클래스는 클래스 이름 뒤에 '-active'를 붙여서 정할 수 있습니다. 커스텀 클래스를 사용한 예제입니다.

-
  ...
-  <ReactCSSTransitionGroup
-    transitionName={ {
-      enter: 'enter',
-      enterActive: 'enterActive',
-      leave: 'leave',
-      leaveActive: 'leaveActive',
-      appear: 'appear',
-      appearActive: 'appearActive'
-    } }>
-    {item}
-  </ReactCSSTransitionGroup>
-
-  <ReactCSSTransitionGroup
-    transitionName={ {
-      enter: 'enter',
-      leave: 'leave',
-      appear: 'appear'
-    } }>
-    {item2}
-  </ReactCSSTransitionGroup>
-  ...
-

애니메이션 그룹이 작동하려면 마운트가 필요 #

-

자식들에게 트랜지션을 적용하려면 ReactCSSTransitionGroup은 이미 DOM에 마운트되어 있거나 prop transitionAppeartrue로 설정되어야만 합니다. 예를 들어, 밑의 코드는 동작하지 않을 것입니다. 왜냐하면 ReactCSSTransitionGroup 안에서 새 아이템을 마운트하는 대신 새 아이템과 같이 ReactCSSTransitionGroup를 마운트했기 때문입니다. 이 것을 위에 있는 시작하기 항목과 비교해보세요.

-
  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          <ReactCSSTransitionGroup transitionName="example">
-            {item}
-          </ReactCSSTransitionGroup>
-        </div>
-      );
-    }, this);
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Add Item</button>
-        {items}
-      </div>
-    );
-  }
-

아이템 하나이거나 없을 때의 애니메이션 #

-

위의 예제에서 ReactCSSTransitionGroup에 아이템 목록을 렌더했지만, ReactCSSTransitionGroup의 자식은 하나이거나 없을 수도 있습니다. 이는 한 엘리먼트가 들어오고 나가는 것의 애니메이션을 가능하게 합니다. 비슷하게, 현재 엘리먼트가 나가는 동안 새 앨리먼트의 애니메이션을 하면, 새 엘리먼트가 현재 엘리먼트를 교체하는 애니메이션을 만들 수 있습니다. 예를 들어 이렇게 간단한 이미지 회전 베너(carousel)를 구현할 수 있습니다.

-
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
-
-var ImageCarousel = React.createClass({
-  propTypes: {
-    imageSrc: React.PropTypes.string.isRequired
-  },
-  render: function() {
-    return (
-      <div>
-        <ReactCSSTransitionGroup 
-          transitionName="carousel" 
-          transitionEnterTimeout={300} 
-          transitionLeaveTimeout={300}>
-          <img src={this.props.imageSrc} key={this.props.imageSrc} />
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-

애니메이션 비활성화 #

-

원한다면 enterleave 애니메이션을 비활성화 할 수 있습니다. 예를 들어, enter 애니메이션만 필요하고 leave 애니메이션은 필요없지만, ReactCSSTransitionGroup이 DOM 노드를 없애기 전 애니메이션이 완료되길 기다리고 있는 경우에 사용할 수 있습니다. ReactCSSTransitionGrouptransitionEnter={false}transitionLeave={false} props를 추가하면 그 애니메이션을 비활성화 할 수 있습니다.

- -
-

주의:

- -

ReactCSSTransitionGroup를 사용할 때는, 트랜지션이 종료되었을 때나 애니메이션 근처에서 더 복잡한 로직을 실행할 때 컴포넌트에 통지할 방법이 없습니다. 보다 세밀하게 제어하고 싶다면, 커스텀 트랜지션에 필요한 훅을 제공하는 저수준 ReactTransitionGroup API를 이용할 수 있습니다.

-
-

저수준 API: ReactTransitionGroup #

-

ReactTransitionGroup은 애니메이션의 기초입니다. 이는 require('react-addons-transition-group')으로 접근할 수 있습니다. 위의 예제처럼 자식들이 선언적으로 여기에 추가되거나 삭제되는 경우, 특별한 훅이 이 생명주기에서 호출됩니다.

-

componentWillAppear(callback) #

-

이미 있는 TransitionGroup에 컴포넌트를 추가할 때 호출되는 componentDidMount()와 같이 호출됩니다. 이는 callback이 호출될 때까지 다른 애니메이션을 막습니다. TransitionGroup의 최초 렌더에서만 호출됩니다.

-

componentDidAppear() #

-

이는 componentWillAppear에 넘겨졌던 callback 함수가 호출된 다음에 호출됩니다.

-

componentWillEnter(callback) #

-

이미 있는 TransitionGroup에 컴포넌트를 추가할 때 호출되는 componentDidMount()와 같이 호출됩니다. 이는 callback이 호출될 때까지 다른 애니메이션을 막습니다. TransitionGroup의 최조 렌더에서는 불려지지 않습니다.

-

componentDidEnter() #

-

이는 componentWillEnter에 넘겨주었던 callback 함수가 호출된 다음에 호출됩니다.

-

componentWillLeave(callback) #

-

이는 ReactTransitionGroup에서 자식이 제거되었을 때 호출됩니다. 자식이 제거되었다고 해도 ReactTransitionGroupcallback이 호출될 때까지 DOM에 자식을 남겨둡니다.

-

componentDidLeave() #

-

이는 willLeave callback이 호출될 때 호출됩니다. (componentWillUnmount와 같은 타이밍)

-

다른 컴포넌트 렌더하기 #

-

기본적으로 ReactTransitionGroupspan으로 렌더합니다. component prop으로 이 행동을 바꿀 수 있습니다. 예를 들어, <ul>을 렌더하고 싶다면 이렇게 하면 됩니다.

-
<ReactTransitionGroup component="ul">
-  ...
-</ReactTransitionGroup>
-
-

React가 렌더할 수 있는 DOM 컴포넌트는 전부 사용할 수 있습니다. 하지만 component가 DOM 컴포넌트일 필요는 없습니다. React 컴포넌트라면 무엇이든 넣을 수 있습니다. 직접 구현한 컴포넌트여도 됩니다! 그냥 component={List}를 적으면 컴포넌트는 this.props.children로 받을 수 있습니다.

- -

사용자 정의를 포함한 어떤 프로퍼티도 렌더된 컴포넌트의 프로퍼티가 됩니다. 예를 들어, <ul>에 CSS 클래스를 넣어서 렌더하려면 이렇게 하면 됩니다.

-
<ReactTransitionGroup component="ul" className="animated-list">
-  ...
-</ReactTransitionGroup>
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/animation-zh-CN.html b/docs/animation-zh-CN.html deleted file mode 100644 index 0bd67a3fb5..0000000000 --- a/docs/animation-zh-CN.html +++ /dev/null @@ -1,697 +0,0 @@ - - - - - - - 动画 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 动画 -

-
- -

React 提供了一个 ReactTransitionGroup 插件作为动画的底层API,和一个 ReactCSSTransitionGroup 用于轻松实现基础的CSS动画和过渡。

-

高级 API: ReactCSSTransitionGroup #

-

ReactCSSTransitionGroup 基于 ReactTransitionGroup 是一个当React组件进入或离开DOM时,执行CSS动画和过渡的简单方法。它的灵感来自于杰出的 ng-animate 库。

-

入门指南 #

-

ReactCSSTransitionGroupReactTransitions 的接口。这是一个简单的元素,包裹了所有你感兴趣的动画组件。这里是一个淡入和淡出列表项目的例子。

-
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
-
-var TodoList = React.createClass({
-  getInitialState: function() {
-    return {items: ['hello', 'world', 'click', 'me']};
-  },
-  handleAdd: function() {
-    var newItems =
-      this.state.items.concat([prompt('Enter some text')]);
-    this.setState({items: newItems});
-  },
-  handleRemove: function(i) {
-    var newItems = this.state.items.slice();
-    newItems.splice(i, 1);
-    this.setState({items: newItems});
-  },
-  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          {item}
-        </div>
-      );
-    }.bind(this));
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Add Item</button>
-        <ReactCSSTransitionGroup 
-          transitionName="example" 
-          transitionEnterTimeout={500} 
-          transitionLeaveTimeout={300}>
-          {items}
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-
-
-

注意:

- -

你必须为ReactCSSTransitionGroup的所有子级提供 key 属性,即使只渲染一个项目。这就是React将决定哪一个子级进入,离开,或者停留

-
- -

在这个组件,当一个新的项目被添加到 ReactCSSTransitionGroup ,他将得到example-enter CSS类 并且在下一刻example-enter-active CSS类被添加。这是一个基于transitionName prop 的约定。

- -

你可以使用这些类来触发CSS动画和过渡。比如,尝试添加这个CSS和添加一个新的列表项:

-
.example-enter {
-  opacity: 0.01;
-}
-
-.example-enter.example-enter-active {
-  opacity: 1;
-  transition: opacity 500ms ease-in;
-}
-
-.example-leave {
-  opacity: 1;
-}
-
-.example-leave.example-leave-active {
-  opacity: 0.01;
-  transition: opacity 300ms ease-in;
-}
-
-

你会注意到动画持续时间需要被同时在CSS和渲染方法里被指定;这告诉React什么时候从元素中移除动画类,并且 -- 如果它正在离开 -- 何时从DOM移除元素。

-

让初始化挂载动画 #

-

ReactCSSTransitionGroup 提供了可选的prop transitionAppear,来为在组件初始挂载添加一个额外的过渡阶段。 通常在初始化挂载时没有过渡阶段因为transitionAppear 的默认值为false。下面是一个传递transitionAppear 为值true的例子。

-
  render: function() {
-    return (
-      <ReactCSSTransitionGroup 
-        transitionName="example" 
-        transitionAppear={true} 
-        transitionAppearTimeout={500}>
-        <h1>Fading at Initial Mount</h1>
-      </ReactCSSTransitionGroup>
-    );
-  }
-
-

在初始化挂载时 ReactCSSTransitionGroup 将获得example-appear CSS类 并且example-appear-active CSS 类在下一刻被添加。

-
.example-appear {
-  opacity: 0.01;
-}
-
-.example-appear.example-appear-active {
-  opacity: 1;
-  transition: opacity .5s ease-in;
-}
-
-

在初始化挂载,所有的 ReactCSSTransitionGroup 子级将会 appear 但不 enter。然而,所有后来添加到已存在的 ReactCSSTransitionGroup 的子级将 enter 但不 appear

- -
-

注意:

- -

prop transitionAppear 在版本 0.13 被添加到 ReactCSSTransitionGroup。为了保持向后兼容,默认值被设置为 false

-
-

制定类 #

-

可以为你的每一步过渡使用制定类名字。代理传递一个字符串到transitionName,你可以传递一个含有enter 或者leave 类名的对象,或者一个含有 enter, enter-active, leave-active, 和 leave 类名的对象。只要提供了enter 和 leave 的类,enter-active 和 leave-active 类会被决定为后缀'-active' 到类名的尾部。这里是两个使用制定类的例子:

-
  ...
-  <ReactCSSTransitionGroup
-    transitionName={ {
-      enter: 'enter',
-      enterActive: 'enterActive',
-      leave: 'leave',
-      leaveActive: 'leaveActive',
-      appear: 'appear',
-      appearActive: 'appearActive'
-    } }>
-    {item}
-  </ReactCSSTransitionGroup>
-
-  <ReactCSSTransitionGroup
-    transitionName={ {
-      enter: 'enter',
-      leave: 'leave',
-      appear: 'appear'
-    } }>
-    {item2}
-  </ReactCSSTransitionGroup>
-  ...
-

动画组必须挂载才工作 #

-

为了使过渡效果应用到子级上,ReactCSSTransitionGroup必须已经挂载到了DOM或者 prop transitionAppear 必须被设置为 true。下面的例子不会工作,因为 ReactCSSTransitionGroup 随同新项目被挂载,而不是新项目在它内部被挂载。将这与上面的入门指南部分比较一下,看看不同。

-
  render: function() {
-    var items = this.state.items.map(function(item, i) {
-      return (
-        <div key={item} onClick={this.handleRemove.bind(this, i)}>
-          <ReactCSSTransitionGroup transitionName="example">
-            {item}
-          </ReactCSSTransitionGroup>
-        </div>
-      );
-    }, this);
-    return (
-      <div>
-        <button onClick={this.handleAdd}>Add Item</button>
-        {items}
-      </div>
-    );
-  }
-

动画一个或者零个项目 Animating One or Zero Items #

-

在上面的例子中,我们渲染了一系列的项目到ReactCSSTransitionGroup里。然而 ReactCSSTransitionGroup 的子级同样可以是一个或零个项目。这使它能够动画化单个元素的进入和离开。同样,你可以动画化一个新的元素替换当前元素。例如,我们可以像这样实现一个简单的图片轮播器:

-
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
-
-var ImageCarousel = React.createClass({
-  propTypes: {
-    imageSrc: React.PropTypes.string.isRequired
-  },
-  render: function() {
-    return (
-      <div>
-        <ReactCSSTransitionGroup 
-          transitionName="carousel" 
-          transitionEnterTimeout={300} 
-          transitionLeaveTimeout={300}>
-          <img src={this.props.imageSrc} key={this.props.imageSrc} />
-        </ReactCSSTransitionGroup>
-      </div>
-    );
-  }
-});
-

禁用动画 #

-

如果你想,你可以禁用 enter 或者 leave 动画。例如,有时你可能想要一个 enter 动画,不要 leave 动画,但是 ReactCSSTransitionGroup 会在移除你的DOM节点之前等待一个动画完成。你可以添加transitionEnter={false} 或者 transitionLeave={false} props 到 ReactCSSTransitionGroup 来禁用这些动画。

- -
-

注意:

- -

当使用 ReactCSSTransitionGroup 时,没有办法通知你的组件何时过渡效果结束或者在动画时执行任何复杂的逻辑运算。如果你想要更多细粒度的控制,你可以使用底层的 ReactTransitionGroup API,它提供了你自定义过渡效果所需要的挂钩。

-
-

底层 API: ReactTransitionGroup #

-

ReactTransitionGroup是动画的基础。它通过 require('react-addons-transition-group') 访问。当子级被声明式的从其中添加或移除(就像上面的例子)时,特殊的生命周期挂钩会在它们上面被调用。

-

componentWillAppear(callback) #

-

对于被初始化挂载到 TransitionGroup 的组件,它和 componentDidMount() 在相同时间被调用 。它将会阻塞其它动画发生,直到callback被调用。它只会在 TransitionGroup 初始化渲染时被调用。

-

componentDidAppear() #

-

在 传给componentWillAppear回调 函数被调用后调用。

-

componentWillEnter(callback) #

-

对于被添加到已存在的 TransitionGroup 的组件,它和 componentDidMount() 在相同时间被调用 。它将会阻塞其它动画发生,直到callback被调用。它不会在 TransitionGroup 初始化渲染时被调用。

-

componentDidEnter() #

-

在传给 componentWillEnter回调函数被调用之后调用。

-

componentWillLeave(callback) #

-

在子级从 ReactTransitionGroup 中移除时调用。虽然子级被移除了,ReactTransitionGroup 将会保持它在DOM中,直到callback被调用。

-

componentDidLeave() #

-

willLeave callback 被调用的时候调用(与 componentWillUnmount 同一时间)。

-

渲染一个不同的组件 #

-

默认情况下 ReactTransitionGroup 渲染为一个 span。你可以通过提供一个 component prop 来改变这种行为。例如,下面是你将如何渲染一个<ul>

-
<ReactTransitionGroup component="ul">
-  ...
-</ReactTransitionGroup>
-
-

每一个React能渲染的DOM组件都是可用的。然而,组件不需要是一个DOM组件。它可以是任何你想要的React组件;甚至是你自己已经写好的!只要写 component={List} 你的组件会收到 this.props.children

- -

任何额外的、用户定义的属性将会成为已渲染的组件的属性。例如,以下是你将如何渲染一个带有css类的 <ul>

-
<ReactTransitionGroup component="ul" className="animated-list">
-  ...
-</ReactTransitionGroup>
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/animation.html b/docs/animation.html index e6239e8d7b..e79c29e323 100644 --- a/docs/animation.html +++ b/docs/animation.html @@ -1,12 +1,14 @@ + + - Animation | React - - + Animation Add-Ons - React + + @@ -44,413 +46,47 @@
- - - -
- -
+ +
+ +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Manipolazione del Nome di Classe -

-
- -
-

NOTA:

- -

Questo modulo esiste adesso in forma separata come JedWatson/classnames ed è indipendente da React. Questo add-on verrà quindi rimosso nell'immediato futuro.

-
- -

classSet() è una elegante utility per manipolare facilmente la stringa dell'attributo class del DOM.

- -

Ecco uno scenario comune e la sua soluzione senza classSet():

-
// all'interno di un componente React `<Message />`
-render: function() {
-  var classString = 'message';
-  if (this.props.isImportant) {
-    classString += ' message-important';
-  }
-  if (this.props.isRead) {
-    classString += ' message-read';
-  }
-  // 'message message-important message-read'
-  return <div className={classString}>Fantastico, vediamoci lì.</div>;
-}
-
-

Questo può facilmente diventare noioso, in quanto assegnare stringhe per nomi di classi può essere difficile da leggere e soggetto ad errori. classSet() risolve questo problema:

-
render: function() {
-  var cx = React.addons.classSet;
-  var classes = cx({
-    'message': true,
-    'message-important': this.props.isImportant,
-    'message-read': this.props.isRead
-  });
-  // same final string, but much cleaner
-  return <div className={classes}>Fantastico, vediamoci lì.</div>;
-}
-
-

Quando usi classSet(), passa un oggetto le cui chiavi sono i nomi di classe CSS di cui potresti o meno avere bisogno. Valori di verità risulteranno nell'inclusione della chiave nella stringa risultante.

- -

classSet() ti permette inoltre di passare nomi di classe che devono essere concatenati come argomenti:

-
render: function() {
-  var cx = React.addons.classSet;
-  var importantModifier = 'message-important';
-  var readModifier = 'message-read';
-  var classes = cx('message', importantModifier, readModifier);
-  // Final string is 'message message-important message-read'
-  return <div className={classes}>Fantastico, vediamoci lì.</div>;
-}
-
-

Niente più hack per concatenare le stringhe!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/class-name-manipulation-ja-JP.html b/docs/class-name-manipulation-ja-JP.html deleted file mode 100644 index e45c496705..0000000000 --- a/docs/class-name-manipulation-ja-JP.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - - クラス名の操作 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- クラス名の操作 -

-
- -
-

注意: -このモジュールは現在JedWatson/classnamesに独立して存在しており、Reactは変更を検知していません。したがって、こちらは将来削除される予定です。

-
- -

classSet() はDOMの class 文字列を簡単に操作するすっきりとしたユーティリティです。

- -

以下は、 classSet() を使用しない共通なシナリオと解決策です。

-
// `<Message />` などの中のReactコンポーネント
-render: function() {
-  var classString = 'message';
-  if (this.props.isImportant) {
-    classString += ' message-important';
-  }
-  if (this.props.isRead) {
-    classString += ' message-read';
-  }
-  // 'message message-important message-read'
-  return <div className={classString}>Great, I'll be there.</div>;
-}
-
-

上記は、クラス名を文字列として渡しているので、面倒で、読みにくく、エラーが発生しやすくなります。以下のように、 classSet() を使用するとこの問題が解決します。

-
render: function() {
-  var cx = React.addons.classSet;
-  var classes = cx({
-    'message': true,
-    'message-important': this.props.isImportant,
-    'message-read': this.props.isRead
-  });
-  // 同様に最終的には文字列になりますが、クリアにはなります
-  return <div className={classes}>Great, I'll be there.</div>;
-}
-
-

classSet() を使用する際には、キーと、必要であったり、必要でないCSSのクラス名をオブジェクトとして渡してください。値が真であるものはキーとなり、最終的には文字列の一部になります。

- -

classSet() もまた、以下のように連結した文字列の引数としてクラス名を渡します。

-
render: function() {
-  var cx = React.addons.classSet;
-  var importantModifier = 'message-important';
-  var readModifier = 'message-read';
-  var classes = cx('message', importantModifier, readModifier);
-  // 最終的な文字列は 'message message-important message-read'
-  return <div className={classes}>Great, I'll be there.</div>;
-}
-
-

文字列の連結を手で書くのはやめましょう!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/class-name-manipulation-ko-KR.html b/docs/class-name-manipulation-ko-KR.html deleted file mode 100644 index ea6c4ae825..0000000000 --- a/docs/class-name-manipulation-ko-KR.html +++ /dev/null @@ -1,545 +0,0 @@ - - - - - - - 클래스 이름 조작 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 클래스 이름 조작 -

-
- -
-

주의:

- -

이 모듈은 폐기예정입니다. 대신 JedWatson/classnames를 사용하세요.

-
- -

classSet()은 간단히 DOM class 문자열을 조작하는 편리한 도구입니다.

- -

일반적으로 있을법한 경우와 classSet()을 사용하지 않았을 때의 처리법을 보시죠.

-
// 어떤 `<Message />` React 컴포넌트의 안쪽
-render: function() {
-  var classString = 'message';
-  if (this.props.isImportant) {
-    classString += ' message-important';
-  }
-  if (this.props.isRead) {
-    classString += ' message-read';
-  }
-  // 'message message-important message-read'
-  return <div className={classString}>좋아요, 거기서 봅시다.</div>;
-}
-
-

이것은 순식간에 장황해질 수 있습니다. 클래스 이름 문자열은 읽기 어렵고 에러가 발생하기도 쉽죠. classSet()가 이 문제를 해결할 수 있습니다.

-
render: function() {
-  var cx = React.addons.classSet;
-  var classes = cx({
-    'message': true,
-    'message-important': this.props.isImportant,
-    'message-read': this.props.isRead
-  });
-  // 최종 문자열은 동일하지만, 훨씬 깔끔함
-  return <div className={classes}>좋아요, 거기서 봅시다.</div>;
-}
-
-

classSet()을 사용할 때 사용할지 안할지 잘 모르는 CSS 클래스 이름 키와 함께 객체를 전달합니다. true로 간주되는(Truthy) 값은 키를 결과 문자열의 일부로 만듭니다.

- -

classSet()은 클래스 이름을 인자로 넘겨 연결되게 할 수도 있습니다.

-
render: function() {
-  var cx = React.addons.classSet;
-  var importantModifier = 'message-important';
-  var readModifier = 'message-read';
-  var classes = cx('message', importantModifier, readModifier);
-  // 최종 문자열은 'message message-important message-read'
-  return <div className={classes}>좋아요, 거기서 봅시다.</div>;
-}
-
-

복잡한 문자열 연결은 이제 안하셔도 됩니다!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/class-name-manipulation-zh-CN.html b/docs/class-name-manipulation-zh-CN.html deleted file mode 100644 index dcf66fae33..0000000000 --- a/docs/class-name-manipulation-zh-CN.html +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - 类名操纵 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 类名操纵 -

-
- -
-

NOTE:

- -

此模块已被弃用; 用 JedWatson/classnames 替代.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/class-name-manipulation.html b/docs/class-name-manipulation.html deleted file mode 100644 index 5a4733d427..0000000000 --- a/docs/class-name-manipulation.html +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - Class Name Manipulation | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Class Name Manipulation -

-
- -
-

NOTE:

- -

This module has been deprecated; use JedWatson/classnames instead.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/clone-with-props-it-IT.html b/docs/clone-with-props-it-IT.html deleted file mode 100644 index 4dba8f7b88..0000000000 --- a/docs/clone-with-props-it-IT.html +++ /dev/null @@ -1,523 +0,0 @@ - - - - - - - Clonare ReactElements | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Clonare ReactElements -

-
- -
-

Nota: -cloneWithProps è deprecato. Usa React.cloneElement al suo posto.

-
- -

In rare condizioni, potresti voler creare una copia di un elemento React con proprietà diverse da quelle dell'elemento originale. Un esempio è clonare gli elementi passati come this.props.children ed effettuarne il rendering con proprietà diverse:

-
var _makeBlue = function(element) {
-  return React.addons.cloneWithProps(element, {style: {color: 'blue'}});
-};
-
-var Blue = React.createClass({
-  render: function() {
-    var blueChildren = React.Children.map(this.props.children, _makeBlue);
-    return <div>{blueChildren}</div>;
-  }
-});
-
-ReactDOM.render(
-  <Blue>
-    <p>Questo testo è blu.</p>
-  </Blue>,
-  document.getElementById('container')
-);
-
-

cloneWithProps non trasferisce gli attributi key o ref agli elementi clonati. Le proprietà className e style sono automaticamente riunite.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/clone-with-props-ja-JP.html b/docs/clone-with-props-ja-JP.html deleted file mode 100644 index 58d61cea6f..0000000000 --- a/docs/clone-with-props-ja-JP.html +++ /dev/null @@ -1,523 +0,0 @@ - - - - - - - ReactElementsをクローンすること | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- ReactElementsをクローンすること -

-
- -
-

注意: -cloneWithProps は使用不可になりました。React.cloneElementを代わりに使用してください。

-
- -

元のReact要素とは異なるプロパティを持った要素のコピーを作成したいと考える稀なケースがあるかと思います。1つの例としては、以下のように、 this.props.children に渡すように要素をクローンし、異なるプロパティを持つようそれらをレンダリングするものです。

-
var _makeBlue = function(element) {
-  return React.addons.cloneWithProps(element, {style: {color: 'blue'}});
-};
-
-var Blue = React.createClass({
-  render: function() {
-    var blueChildren = React.Children.map(this.props.children, _makeBlue);
-    return <div>{blueChildren}</div>;
-  }
-});
-
-ReactDOM.render(
-  <Blue>
-    <p>This text is blue.</p>
-  </Blue>,
-  document.getElementById('container')
-);
-
-

cloneWithPropskeyref をクローンされた要素に渡すことはありません。 classNamestyle は自動的にマージされます。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/clone-with-props-ko-KR.html b/docs/clone-with-props-ko-KR.html deleted file mode 100644 index dfe4f23b26..0000000000 --- a/docs/clone-with-props-ko-KR.html +++ /dev/null @@ -1,525 +0,0 @@ - - - - - - - ReactElement 클론하기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- ReactElement 클론하기 -

-
- -
-

주의: -cloneWithProps는 비추천입니다. 대신 React.cloneElement를 사용하세요.

-
- -

드문 경우긴 하지만 원래 엘리먼트와 다른 prop을 가진 React 엘리먼트의 복사본을 만들고 싶을 때가 있습니다. 예를 들면 this.props.children에 클론한 엘리먼트를 넘기고 다른 prop으로 렌더링하는 경우 입니다.

-
var cloneWithProps = require('react-addons-clone-with-props');
-
-var _makeBlue = function(element) {
-  return cloneWithProps(element, {style: {color: 'blue'}});
-};
-
-var Blue = React.createClass({
-  render: function() {
-    var blueChildren = React.Children.map(this.props.children, _makeBlue);
-    return <div>{blueChildren}</div>;
-  }
-});
-
-ReactDOM.render(
-  <Blue>
-    <p>This text is blue.</p>
-  </Blue>,
-  document.getElementById('container')
-);
-
-

cloneWithPropskeyref를 클론된 엘리먼트에 전달하지 않습니다. className, style prop은 자동으로 머지됩니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/clone-with-props-zh-CN.html b/docs/clone-with-props-zh-CN.html deleted file mode 100644 index 7a68a92a8b..0000000000 --- a/docs/clone-with-props-zh-CN.html +++ /dev/null @@ -1,525 +0,0 @@ - - - - - - - 克隆 ReactElements | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 克隆 ReactElements -

-
- -
-

注意: -cloneWithProps 被弃用了. 用 React.cloneElement 代替.

-
- -

在很罕见的情况下,你可能需要创建一个 React 元素的拷贝,它与初始的元素有不同的 props。一个例子是克隆这些传递到 this.props.children 的元素并用不同的 props 渲染他们。

-
var cloneWithProps = require('react-addons-clone-with-props');
-
-var _makeBlue = function(element) {
-  return cloneWithProps(element, {style: {color: 'blue'}});
-};
-
-var Blue = React.createClass({
-  render: function() {
-    var blueChildren = React.Children.map(this.props.children, _makeBlue);
-    return <div>{blueChildren}</div>;
-  }
-});
-
-ReactDOM.render(
-  <Blue>
-    <p>This text is blue.</p>
-  </Blue>,
-  document.getElementById('container')
-);
-
-

cloneWithProps 不传递 key 或者 ref 到被克隆的元素。classNamestyle props 被自动合并。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/clone-with-props.html b/docs/clone-with-props.html deleted file mode 100644 index dfaa018518..0000000000 --- a/docs/clone-with-props.html +++ /dev/null @@ -1,525 +0,0 @@ - - - - - - - Cloning ReactElements | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Cloning ReactElements -

-
- -
-

Note: -cloneWithProps is deprecated. Use React.cloneElement instead.

-
- -

In rare situations, you may want to create a copy of a React element with different props from those of the original element. One example is cloning the elements passed into this.props.children and rendering them with different props:

-
var cloneWithProps = require('react-addons-clone-with-props');
-
-var _makeBlue = function(element) {
-  return cloneWithProps(element, {style: {color: 'blue'}});
-};
-
-var Blue = React.createClass({
-  render: function() {
-    var blueChildren = React.Children.map(this.props.children, _makeBlue);
-    return <div>{blueChildren}</div>;
-  }
-});
-
-ReactDOM.render(
-  <Blue>
-    <p>This text is blue.</p>
-  </Blue>,
-  document.getElementById('container')
-);
-
-

cloneWithProps does not transfer key or ref to the cloned element. className and style props are automatically merged.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-api-it-IT.html b/docs/component-api-it-IT.html deleted file mode 100644 index 151bc3f33e..0000000000 --- a/docs/component-api-it-IT.html +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - - API dei Componenti | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- API dei Componenti -

-
- -

React.Component #

-

Istanze di un React Component sono create internamente a React durante il rendering. Queste istanze sono riutilizzate in rendering successivi, e possono essere accedute dai metodi del tuo componente come this. L'unica maniera di ottenere un riferimento a una istanza di un React Component fuori da React è conservare il valore restituito da ReactDOM.render. All'interno di altri Component, puoi utilizzare i ref per ottenere il medesimo risultato.

-

setState #

void setState(
-  function|object nextState,
-  [function callback]
-)
-
-

Effettua una combinazione di nextState nello stato attuale. Questo è il metodo principale che va usato per scatenare aggiornamenti della UI da gestori di eventi e callback di richieste al server.

- -

Il primo argomento può essere un oggetto (contenente zero o più chiavi da aggiornare) o una funzione (con argomenti state e props) che restituisce un oggetto contenente chiavi da aggiornare.

- -

Ecco come utilizzarla passando un oggetto:

-
setState({mykey: 'my new value'});
-
-

È anche possibile passare una funzione con la firma function(state, props). Questo può essere utile in certi casi quando desideri accodare un aggiornamento atomico che consulta i valori precedenti di state+props prima di impostare i nuovi valori. Ad esempio, supponi che vogliamo incrementare un valore nello stato:

-
setState(function(previousState, currentProps) {
-  return {myInteger: previousState.myInteger + 1};
-});
-
-

Il secondo parametro (opzionale) è una funzione callback che verrà eseguita quando setState ha terminato e il rendering del componente è stato effettuato.

- -
-

Note:

- -

MAI modificare this.state direttamente, in quanto chiamare setState() successivamente potrebbe sovrascrivere la modifica fatta. Tratta this.state come se fosse immutabile.

- -

setState() non cambia immediatamente this.state, ma crea una transizione di stato in corso. Accedere this.state subito dopo aver chiamato questo metodo potrebbe potenzialmente restituire il valore precedente.

- -

Non viene garantita alcuna sincronicità per le chiamate di setState, e le chiamate stesse potrebbero essere raggruppate per migliorare le prestazioni.

- -

setState() scatena sempre un ri-rendering a meno che la logica di rendering condizionale venga implementata in shouldComponentUpdate(). Se oggetti mutabili sono usati e la logica non può essere implementata in shouldComponentUpdate(), chiamare setState() solo quando il nuovo stato differisce dal precedente eviterà ri-rendering superflui.

-
-

replaceState #

void replaceState(
-  object nextState,
-  [function callback]
-)
-
-

Come setState(), ma elimina ogni chiave preesistente che non si trova in nextState.

- -
-

Nota:

- -

Questo metodo non è disponibile il componenti class ES6 che estendono React.Component. Potrebbe essere eliminato del tutto in una versione futura di React.

-
-

forceUpdate #

void forceUpdate(
-  [function callback]
-)
-
-

In modo predefinito, quando lo stato o le proprietà del tuo componente cambiano, ne verrà effettuato il ri-rendering. Tuttavia, se questi cambiano implicitamente (ad es.: dati profondi all'interno di un oggetto cambiano senza che l'oggetto stesso cambi) o se il tuo metodo render() dipende da altri dati, puoi istruire React perché riesegua render() chiamando forceUpdate().

- -

Chiamare forceUpdate() causerà la chiamata di render() sul componente, saltando l'esecuzione di shouldComponentUpdate(). Questo scatenerà i normali metodi del ciclo di vita per i componenti figli, incluso il metodo shouldComponentUpdate() di ciascun figlio. React tuttavia aggiornerà il DOM soltanto se il markup effettivamente cambia.

- -

Normalmente dovresti cercare di evitare l'uso di forceUpdate() e leggere soltanto this.props e this.state all'interno di render(). Ciò rende il tuo componente "puro" e la tua applicazione molto più semplice ed efficiente.

-

isMounted #

boolean isMounted()
-
-

isMounted() restituisce true se il rendering del componente è stato effettuato nel DOM, false altrimenti. Puoi usare questo metodo come guardia per chiamate asincrone a setState() o forceUpdate().

- -
-

Nota:

- -

Questo metodo non è disponibile il componenti class ES6 che estendono React.Component. Potrebbe essere eliminato del tutto in una versione futura di React.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-api-ko-KR.html b/docs/component-api-ko-KR.html deleted file mode 100644 index dea8f6475d..0000000000 --- a/docs/component-api-ko-KR.html +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - - 컴포넌트 API | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 컴포넌트 API -

-
- -

React.Component #

-

React 컴포넌트의 인스턴스는 React가 렌더링 시에 내부적으로 만듭니다. 이때 만들어진 인스턴스는 이후의 렌더링에서 다시 사용되고 컴포넌트의 메소드들에서 this 변수로 접근할 수 있습니다. React 외부에서 React 컴포넌트의 핸들을 얻는 방법은 ReactDOM.render의 리턴값을 저장하는 것이 유일합니다. 다른 컴포넌트 안에서 비슷한 결과를 얻으려면 refs를 사용해야 합니다.

-

setState #

void setState(
-  function|object nextState,
-  [function callback]
-)
-
-

nextState를 현재 state에 얕게(shallow) 병합합니다. 이벤트 핸들러와 서버 요청 콜백에서 UI 업데이트를 발생시키기 위해 이 메소드를 주로 사용합니다.

- -

첫번째 인자는 업데이트를 위한 키를 0개 이상 가진 객체이거나 업데이트를 위한 키들을 포함한 객체를 반환하는 함수(의 state나 props)일 수 있습니다.

- -

객체를 사용하는 간단한 예제입니다:

-
setState({mykey: '새로운 값'});
-
-

function(state, props)처럼 인자를 포함한 함수를 넘겨주는 것도 가능합니다. 어떤 값이든 state와 props의 이전 값을 참고해서 원자적인 업데이트를 큐에 추가(enqueue)하려는 경우 이는 유용합니다. 예를 들어 state의 값을 증가 시키려는 경우 같이 처리 가능합니다:

-
setState(function(previousState, currentProps) {
-  return {myInteger: previousState.myInteger + 1};
-});
-
-

두번째 인자는 선택적이며, setState가 한번 완료되고 컴포넌트가 다시 렌더 되었을때 실행되는 콜백 함수입니다.

- -
-

주의:

- -

절대로 this.state를 직접 변경하지 마세요. 그 뒤에 setState()를 호출하면 그동안 변경했던 것이 교체될 수 있습니다. this.state는 변경 불가능한 것으로 생각하시는 것이 좋습니다.

- -

setState()를 호출해도 this.state가 곧바로 변경되지 않고 대기 중인 state transition이 만들어집니다. 이 메소드를 호출한 직후 this.state에 접근하면 바뀌기 전의 값을 리턴할 가능성이 있습니다.

- -

setState에 대한 호출이 동기적으로 처리된다는 보장이 없으며, 성능 향상을 위해 배치 처리될 수 있습니다.

- -

setState()shouldComponentUpdate()에 조건부 렌더링 로직이 구현되어 있지 않다면 항상 재렌더링을 발생시킵니다. 변경 가능한 객체를 사용하고 있고 조건부 렌더링 로직을 shouldComponentUpdate()에 구현할 수 없는 경우라면 새로운 state가 이전 state와 달라지는 경우에만 setState()를 호출하여 불필요한 재렌더링을 피할 수 있습니다.

-
-

replaceState #

void replaceState(
-  object nextState,
-  [function callback]
-)
-
-

setState()와 비슷하지만 기존에 존재하는 state 중 nextState에 없는 키는 모두 삭제됩니다.

- -
-

주의:

- -

이 메소드는 React.Component를 확장한 ES6 class 컴포넌트에서는 사용할 수 없습니다. React의 미래 버전에서 이는 완전히 사라지게 될 것입니다.

-
-

forceUpdate #

void forceUpdate(
-  [function callback]
- )
-
-

기본적으로, 컴포넌트의 state나 props가 변경되면, 컴포넌트는 다시 렌더됩니다. 하지만 이런 변경이 묵시적이거나(예를들어 객체의 변경 없이 깊이 있는 데이터만 변경된 경우) render() 함수가 다른 값에 의존하는 경우, forceUpdate()를 호출해 React에게 render()를 다시 실행할 필요가 있다고 알릴 수 있습니다.

- -

forceUpdate()를 호출하면 shouldComponentUpdate()를 생략하고 해당 컴포넌트 render() 함수가 호출됩니다. 각 자식 컴포넌트에 대해서는 shouldComponentUpdate()를 포함해 보통 라이프 사이클 메서드를 호출합니다. React는 마크업이 변경된 경우에만 DOM을 업데이트합니다.

- -

특별한 경우가 아니면 forceUpdate()는 되도록 피하시고 render()에서는 this.propsthis.state에서만 읽어오세요. 그렇게 하는 것이 컴포넌트를 "순수"하게 하고 애플리케이션을 훨씬 단순하고 효율적으로 만들어줍니다.

-

isMounted #

boolean isMounted()
-
-

isMounted()는 컴포넌트가 DOM에 렌더링되었으면 true를, 아니면 false를 리턴합니다. 비동기적으로 setState()forceUpdate()를 호출할 때 이 메소드를 사용하여 오류를 방지할 수 있습니다.

- -
-

주의:

- -

이 메소드는 React.Component를 확장한 ES6 class 컴포넌트에서는 사용할 수 없습니다. React의 미래 버전에서 이는 완전히 사라지게 될 것입니다.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-api-zh-CN.html b/docs/component-api-zh-CN.html deleted file mode 100644 index 788617d65e..0000000000 --- a/docs/component-api-zh-CN.html +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - - 组件 API | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 组件 API -

-
- -

React.Component #

-

当渲染时,React 组件的实例在 React 内部被创建。这些实例在随后的渲染中被重复使用,并可以在组件方法中通过 this 访问。唯一的在 React 之外获取 React 组件实例句柄的方法是保存 ReactDOM.render 的返回值。在其它组件内,你可以使用 refs 得到相同的结果。

-

setState #

void setState(
-  function|object nextState,
-  [function callback]
-)
-
-

执行一个 nextState 到当前 state 的浅合并。这是你从事件处理器和服务器请求回调用来触发 UI 更新的主要手段。

- -

第一个参数可以是一个对象(包含0或者多个keys来更新)或者一个(state 和 props的)函数,它返回一个包含要更新的keys的对象。

- -

这里是一个简单的运用:

-
setState({mykey: 'my new value'});
-
-

也可以以 function(state, props) 传递一个函数。当你想要把一个在设置任何值之前参考前一次 state+props 的值的原子更新放在队列中 这会有很用。例如,假如我们想在 state 增加一个值:

-
setState(function(previousState, currentProps) {
-  return {myInteger: previousState.myInteger + 1};
-});
-
-

第二个(可选)的参数是一个将会在 setState 完成和组件被重绘后执行的回调函数。

- -
-

注意:

- -

绝对不要 直接改变 this.state,因为之后调用 setState() 可能会替换掉你做的改变。把 this.state 当做是不可变的。

- -

setState() 不会立刻改变 this.state,而是创建一个即将处理的 state 转变。在调用该方法之后访问 this.state 可能会返回现有的值。

- -

setState 的调用没有任何同步性的保证,并且调用可能会为了性能收益批量执行。

- -

setState() 将总是触发一次重绘,除非在 shouldComponentUpdate() 中实现了条件渲染逻辑。如果可变对象被使用了,但又不能在 shouldComponentUpdate() 中实现这种逻辑,仅在新 state 和之前的 state 存在差异的时候调用 setState() 可以避免不必要的重新渲染。

-
-

replaceState #

void replaceState(
-  object nextState,
-  [function callback]
-)
-
-

类似于 setState(),但是删除任何 先前存在但不在 nextState 里的 state 键。

- -
-

注意:

- -

这个方法在从 React.Component 扩展的 ES6 class 组件里不可用。它也许会在未来的 React 版本中被完全移除。

-
-

forceUpdate #

void forceUpdate(
-  [function callback]
-)
-
-

默认情况下,当你的组件的 state 或者 props 改变,你的组件将会重绘。然而,如果它们隐式的改变(例如:在对象深处的数据改变了但没有改变对象本身)或者如果你的 render() 方法依赖于其他的数据,你可以用调用 forceUpdate() 来告诉 React 它需要重新运行 render()

- -

调用 forceUpdate() 将会导致 render() 跳过 shouldComponentUpdate() 在组件上被调用,这会为子级触发正常的生命周期方法。包括每个子级的 shouldComponentUpdate() 方法。如果标记改变了,React 仍仅只更新 DOM。

- -

通常你应该试着避免所有对 forceUpdate() 的使用并且在 render() 里只从 this.propsthis.state 读取。这会使你的组件 "纯粹" 并且你的组件会更简单和高效。

-

isMounted #

boolean isMounted()
-
-

如果组件渲染到了 DOM 中,isMounted() 返回 true,否则返回 false。可以使用该方法来控制对 setState()forceUpdate() 的异步调用。

- -
-

注意:

- -

这个方法在从 React.Component 扩展的 ES6 class 组件里不可用。它也许会在未来的 React 版本中被完全移除,所以你也要移除它 start migrating away from isMounted() now

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-api.html b/docs/component-api.html deleted file mode 100644 index d42971ba50..0000000000 --- a/docs/component-api.html +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - - Component API | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Component API -

-
- -

React.Component #

-

Instances of a React Component are created internally in React when rendering. These instances are reused in subsequent renders, and can be accessed in your component methods as this. The only way to get a handle to a React Component instance outside of React is by storing the return value of ReactDOM.render. Inside other Components, you may use refs to achieve the same result.

-

setState #

void setState(
-  function|object nextState,
-  [function callback]
-)
-
-

Performs a shallow merge of nextState into current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks.

- -

The first argument can be an object (containing zero or more keys to update) or a function (of state and props) that returns an object containing keys to update.

- -

Here is the simple object usage:

-
setState({mykey: 'my new value'});
-
-

It's also possible to pass a function with the signature function(state, props). This can be useful in some cases when you want to enqueue an atomic update that consults the previous value of state+props before setting any values. For instance, suppose we wanted to increment a value in state:

-
setState(function(previousState, currentProps) {
-  return {myInteger: previousState.myInteger + 1};
-});
-
-

The second (optional) parameter is a callback function that will be executed once setState is completed and the component is re-rendered.

- -
-

Notes:

- -

NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

- -

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

- -

There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

- -

setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate(). If mutable objects are being used and the logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.

-
-

replaceState #

void replaceState(
-  object nextState,
-  [function callback]
-)
-
-

Like setState() but deletes any pre-existing state keys that are not in nextState.

- -
-

Note:

- -

This method is not available on ES6 class components that extend React.Component. It may be removed entirely in a future version of React.

-
-

forceUpdate #

void forceUpdate(
-  [function callback]
-)
-
-

By default, when your component's state or props change, your component will re-render. However, if these change implicitly (eg: data deep within an object changes without changing the object itself) or if your render() method depends on some other data, you can tell React that it needs to re-run render() by calling forceUpdate().

- -

Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child. React will still only update the DOM if the markup changes.

- -

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient.

-

isMounted #

boolean isMounted()
-
-

isMounted() returns true if the component is rendered into the DOM, false otherwise. You can use this method to guard asynchronous calls to setState() or forceUpdate().

- -
-

Note:

- -

This method is not available on ES6 class components that extend React.Component. It will likely be removed entirely in a future version of React, so you might as well start migrating away from isMounted() now.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-specs-it-IT.html b/docs/component-specs-it-IT.html deleted file mode 100644 index 0d7e5e2cd5..0000000000 --- a/docs/component-specs-it-IT.html +++ /dev/null @@ -1,623 +0,0 @@ - - - - - - - Specifica dei Componenti e Ciclo di Vita | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Specifica dei Componenti e Ciclo di Vita -

-
- -

Specifica dei Componenti #

-

Quando crei una classe di componente invocando React.createClass(), devi fornire un oggetto specifica che contiene un metodo render che può contenere opzionalmete altri metodi del ciclo di vita descritti di seguito.

- -
-

Nota:

- -

È anche possibile usare pure classi JavaScript come classi di componente. Queste classi possono implementare la maggior parte degli stessi metodi, sebbene vi siano delle differenze. Per maggiori informazioni su queste differenze, leggi la nostra documentazione sulle classi ES6.

-
-

render #

ReactElement render()
-
-

Il metodo render() è richiesto.

- -

Quando viene chiamato, dovrebbe esaminare this.props e this.state e restituire un singolo elemento figlio. Questo elemento figlio può essere sia una rappresentazione virtuale di un componente DOM nativo (come <div /> o React.DOM.div()) o un altro componente composito che hai definito tu stesso.

- -

Puoi anche restituire null o false per indicare che desideri che non venga visualizzato nulla. Dietro le quinte, React visualizza un tag <noscript> per lavorare con il nostro attuale algoritmo di differenza. Quando si restituisce null o false, ReactDOM.findDOMNode(this) restituirà null.

- -

La funzione render() dovrebbe essere pura, nel senso che non modifica lo stato del componente, restituisce lo stesso risultato ogni volta che viene invocato, e non legge o scrive il DOM o interagisce in altro modo con il browser (ad es. usando setTimeout). Se devi interagire con il browser, effettua le tue operazioni in componentDidMount() o negli altri metodi del ciclo di vita. Mantenere render() puro rende il rendering lato server più praticabile e rende i componenti più facili da comprendere.

-

getInitialState #

object getInitialState()
-
-

Invocato una volta prima che il componente venga montato. Il valore di ritorno sarà usato come il valore iniziale di this.state.

- -
-

Nota:

- -

Questo metodo non è disponibile il componenti class ES6 che estendono React.Component. Per maggiori informazioni, leggi la nostra documentazione sulle classi ES6.

-
-

getDefaultProps #

object getDefaultProps()
-
-

Invocato una volta e conservato quando la classe è creata. I valori nella mappa saranno impostati in this.props se tale proprietà non è specificata dal componente genitore (ad es. usando un controllo in).

- -

Questo metodo è invocato prima che un'istanza sia creata e quindi non può dipendere da this.props. Inoltre, tieni presente che ogni oggetto complesso restituito da getDefaultProps() sarà condiviso tra le diverse istanze, non copiato.

-

propTypes #

object propTypes
-
-

L'oggetto propTypes ti permette di validare le proprietà passate ai tuoi componenti. Per maggiori informazioni su propTypes, leggi Componenti Riutilizzabili.

-

mixins #

array mixins
-
-

L'array mixins ti permette di usare i mixin per condividere il comportamento tra componenti multipli. Per maggiori informazioni sui mixin, leggi Componenti Riutilizzabili.

-

statics #

object statics
-
-

L'oggetto statics ti permette di definire metodi statici che possono essere chiamati sulla classe del componente. Ad esempio:

-
var MyComponent = React.createClass({
-  statics: {
-    customMethod: function(foo) {
-      return foo === 'bar';
-    }
-  },
-  render: function() {
-  }
-});
-
-MyComponent.customMethod('bar');  // true
-
-

I metodi definiti in questo blocco sono statici, ovvero puoi eseguirli prima che un'istanza del componente venga creata, e i metodi non hanno accesso alle proprietà e lo stato dei tuoi componenti. Se desideri confrontare i valori delle proprietà in un metodo statico, devi farle passare dal chiamante al metodo statico tramite un argomento.

-

displayName #

string displayName
-
-

La stringa displayName viene usata nei messaggi di debug. JSX imposta questo valore automaticamente; vedi JSX in Profondità.

-

Metodi del Ciclo di Vita #

-

Vari metodi vengono eseguiti durante precisi momenti del ciclo di vita di un componente.

-

Montaggio: componentWillMount #

void componentWillMount()
-
-

Invocato una volta, sia sul client che sul server, immediatamente prima che il rendering iniziale abbia luogo. Se chiami setState all'interno di questo metodo, render() vedrà lo stato aggiornato e sarà eseguito solo una volta nonostante il cambiamento di stato.

-

Montaggio: componentDidMount #

void componentDidMount()
-
-

Invocato una volta, solo sul client (e non sul server), immediatamente dopo che il rendering iniziale ha avuto luogo. A questo punto del ciclo di vita, il componente ha una rappresentazione DOM che puoi accedere attraverso ReactDOM.findDOMNode(this). Il metodo componentDidMount() dei componenti figli è invocato prima di quello dei componenti genitori.

- -

Se desideri integrare con altri framework JavaScript, impostare dei timer usando setTimeout o setInterval, oppure inviare richieste AJAX, effettua tali operazioni in questo metodo.

-

Aggiornamento: componentWillReceiveProps #

void componentWillReceiveProps(
-  object nextProps
-)
-
-

Invocato quando un componente sta ricevendo nuove proprietà. Questo metodo non viene chiamato durante il rendering iniziale.

- -

Usa questo metodo come opportunità per reagire a una transizione di proprietà prima che render() venga chiamato, aggiornando lo stato usando this.setState(). I vecchi valori delle proprietà possono essere letti tramite this.props. Chiamare this.setState() all'interno di questa funzione non scatenerà un rendering addizionale.

-
componentWillReceiveProps: function(nextProps) {
-  this.setState({
-    likesIncreasing: nextProps.likeCount > this.props.likeCount
-  });
-}
-
-
-

Nota:

- -

Non esiste un metodo analogo componentWillReceiveState. Una imminente transizione delle proprietà potrebbe causare un cambiamento di stato, ma il contrario non è vero. Se devi effettuare delle operazioni in risposta a un cambiamento di stato, usa componentWillUpdate.

-
-

Aggiornamento: shouldComponentUpdate #

boolean shouldComponentUpdate(
-  object nextProps, object nextState
-)
-
-

Invocato prima del rendering quando vengono ricevuti nuove proprietà o un nuovo stato. Questo metodo non viene chiamato per il rendering iniziale o quando viene usato forceUpdate.

- -

Usa questo metodo come opportunità per restituire false quando si è certi che la transizione alle nuove proprietà e al nuovo stato non richieda un aggiornamento del componente.

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return nextProps.id !== this.props.id;
-}
-
-

Se shouldComponentUpdate restituisce false, allora render() sarà saltato completamente fino al prossimo cambiamento di stato. Inoltre, componentWillUpdate e componentDidUpdate non verranno chiamati.

- -

In modo predefinito, shouldComponentUpdate restituisce sempre true per evitare bachi subdoli quando state viene modificato direttamente, ma se hai l'accortezza di trattare sempre state come immutabile e accedere a props e state in sola lettura in render(), allora puoi tranquillamente ridefinire shouldComponentUpdate con un'implementazione che confronta i vecchi valori di props e state con quelli nuovi.

- -

Se le prestazioni diventano un collo di bottiglia, specialmente in presenza di decine o centinaia di componenti, usa shouldComponentUpdate per accelerare la tua applicazione.

-

Aggiornamento: componentWillUpdate #

void componentWillUpdate(
-  object nextProps, object nextState
-)
-
-

Invocato immediatamente prima del rendering quando nuove proprietà o un nuovo stato vengono ricevuti. Questo metodo non viene chiamato per il rendering iniziale.

- -

Usa questo metodo come opportunità per effettuare la preparazione prima che si verifichi un aggiornamento.

- -
-

Nota:

- -

Non puoi usare this.setState() in questo metodo. Se devi aggiornare lo stato in risposta al cambiamento di una proprietà, usa componentWillReceiveProps.

-
-

Aggiornamento: componentDidUpdate #

void componentDidUpdate(
-  object prevProps, object prevState
-)
-
-

Invocato immediatamente dopo che gli aggiornamenti del componente sono stati trasmessi al DOM. Questo metodo non viene chiamato per il rendering iniziale.

- -

Usa questo metodo come opportunità per operare sul DOM quando il componente è stato the component has been updated.

-

Smontaggio: componentWillUnmount #

void componentWillUnmount()
-
-

Invocato immediatamente prima che un componente venga smontato dal DOM.

- -

Effettua la necessaria pulizia in questo metodo, come invalidare i timer o ripulire ciascun elemento DOM creato all'interno di componentDidMount.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-specs-ko-KR.html b/docs/component-specs-ko-KR.html deleted file mode 100644 index 480b75a956..0000000000 --- a/docs/component-specs-ko-KR.html +++ /dev/null @@ -1,624 +0,0 @@ - - - - - - - 컴포넌트 명세와 생명주기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 컴포넌트 명세와 생명주기 -

-
- -

컴포넌트 명세 #

-

React.createClass()를 호출하여 컴포넌트 클래스를 생성할 때, render 메소드를 포함한 명세 객체를 제공해야 합니다. 또한 필요한 경우 여기에서 설명하는 다른 생명주기 메소드를 명세 객체에 추가로 제공할 수 있습니다.

- -
-

주의:

- -

그냥 JavaScript 클래스를 컴포넌트 클래스로 사용할 수도 있습니다. 이 클래스는 구현할 수 있는 메소드가 거의 같지만 약간의 차이가 있습니다. 차이에 관한 더 자세한 정보는 ES6 클래스를 읽어보세요.

-
-

render #

ReactElement render()
-
-

render() 메소드는 필수 항목입니다.

- -

호출되면 this.propsthis.state를 토대로 하나의 자식 엘리먼트를 리턴합니다. 이 자식 엘리먼트는 네이티브 DOM 컴포넌트의 가상 표현 (<div />React.DOM.div() 등) 또는 직접 정의한 조합(composite) 컴포넌트가 될 수 있습니다.

- -

아무 것도 렌더링되지 않도록 하려면 null이나 false를 리턴합니다. React는 지금의 차이 비교 알고리즘이 작동할 수 있도록 내부적으로는 <noscript> 태그를 렌더링합니다. null이나 false를 리턴한 경우, ReactDOM.findDOMNode(this)null을 리턴합니다.

- -

render() 함수는 순수 함수여야 합니다. 즉, 컴포넌트의 상태를 변경하지 않고, 여러번 호출해도 같은 결과를 리턴하며, DOM을 읽고 쓰거나 브라우저와 상호작용(예를 들어 setTimeout를 사용)하지 않아야 합니다. 브라우저와 상호작용해야 한다면 componentDidMount()나 다른 생명주기 메소드에서 수행해야 합니다. render() 함수를 순수 함수로 유지하면 서버 렌더링이 훨씬 쓸만해지고 컴포넌트에 대해 생각하기 쉬워집니다.

-

getInitialState #

object getInitialState()
-
-

컴포넌트가 마운트되기 전에 한번 호출됩니다. 리턴값은 this.state의 초기값으로 사용됩니다.

- -
-

주의:

- -

이 메소드는 React.Component를 확장한 ES6 class 컴포넌트에서는 사용할 수 없습니다. 관한 더 자세한 정보는 ES6 클래스를 읽어보세요.

-
-

getDefaultProps #

object getDefaultProps()
-
-

클래스가 생성될 때 한번 호출되고 캐시됩니다. 부모 컴포넌트에서 prop이 넘어오지 않은 경우 (in 연산자로 확인) 매핑의 값이 this.props에 설정됩니다.

- -

이 메소드는 인스턴스가 만들어지기 전에 호출되므로 this.props에 의존할 수 없습니다. 그리고 getDefaultProps()의 리턴값에 포함된 복잡한 객체는 복사되지 않고 인스턴스 간에 공유됩니다.

-

propTypes #

object propTypes
-
-

propTypes 객체는 컴포넌트에 넘어오는 props가 올바른지 검사할 수 있게 해줍니다. propTypes에 대한 자세한 정보는 재사용 가능한 컴포넌트를 참고하세요.

-

mixins #

array mixins
-
-

mixins 배열은 여러 컴포넌트 사이에 동작을 공유하는 믹스인을 사용할 수 있게 해줍니다. 믹스인에 대한 자세한 정보는 재사용 가능한 컴포넌트를 참고하세요.

-

statics #

object statics
-
-

statics 객체는 컴포넌트 클래스의 스태틱 메소드를 정의할 수 있게 해줍니다. 에를 들어:

-
var MyComponent = React.createClass({
-  statics: {
-    customMethod: function(foo) {
-      return foo === 'bar';
-    }
-  },
-  render: function() {
-  }
-});
-
-MyComponent.customMethod('bar');  // true
-
-

이 블럭 안에서 정의된 메소드는 인스턴스를 하나도 만들지 않은 시점에도 호출할 수 있고, 컴포넌트의 props나 state에 접근할 수 없습니다. 스태틱 메소드에서 props의 값을 확인하려면 호출자가 스태틱 메소드에 props를 인자로 넘기도록 해야합니다.

-

displayName #

string displayName
-
-

displayName 문자열은 디버그 메시지에 사용됩니다. JSX는 이 값을 자동으로 설정합니다. JSX 깊이 알기를 참고하세요.

-

생명주기 메소드 #

-

컴포넌트의 생명주기에서 특정 시점마다 실행되는 메소드들입니다.

-

마운트 시: componentWillMount #

void componentWillMount()
-
-

최초 렌더링이 일어나기 직전에 클라이언트 및 서버에서 한번 호출됩니다. 이 메소드 안에서 setState를 호출하면, render()에서 업데이트된 state를 확인할 수 있고 state가 변함에도 불구하고 render()가 한번만 실행됩니다.

-

마운트 시: componentDidMount #

void componentDidMount()
-
-

최초 렌더링이 일어난 다음 클라이언트에서만 한번 호출됩니다. (서버에서는 호출되지 않습니다.) 이 시점에 자식의 refs들에 접근 할 수 있습니다. (기본 DOM 표현에 접근하는 등). 자식 컴포넌트의 componentDidMount() 메소드는 부모 컴포넌트보다 먼저 호출됩니다.

- -

다른 JavaScript 프레임워크를 연동하거나, setTimeout/setInterval로 타이머를 설정하고 AJAX 요청을 보내는 등의 작업을 이 메소드에서 합니다.

-

업데이트 시: componentWillReceiveProps #

void componentWillReceiveProps(
-  object nextProps
-)
-
-

컴포넌트가 새로운 props를 받을 때 호출됩니다. 이 메소드는 최초 렌더링 시에는 호출되지 않습니다.

- -

render()가 호출되기 전에 prop의 변화를 감지하여 this.setState()를 호출해서 state를 업데이트할 수 있습니다. 이전 props는 this.props로 접근할 수 있습니다. 이 함수 안에서 this.setState()를 호출해도 추가 렌더링이 발생하지 않습니다.

-
componentWillReceiveProps: function(nextProps) {
-  this.setState({
-    likesIncreasing: nextProps.likeCount > this.props.likeCount
-  });
-}
-
-
-

주의:

- -

componentWillReceiveState에 해당하는 메소드는 없습니다. prop이 변할 때 state가 바뀔 수는 있지만, 그 역은 불가능합니다. state의 변화에 따라 작업을 실행해야 하면 componentWillUpdate를 사용하세요.

-
-

업데이트 시: shouldComponentUpdate #

boolean shouldComponentUpdate(
-  object nextProps, object nextState
-)
-
-

새로운 props 또는 state를 받아 렌더링을 하기 전에 호출됩니다. 최초 렌더링 시나 forceUpdate를 사용하는 경우에는 호출되지 않습니다.

- -

새로운 props와 state가 컴포넌트 업데이트를 필요로 하지 않는 것이 확실하다면 -false를 리턴하세요.

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return nextProps.id !== this.props.id;
-}
-
-

shouldComponentUpdate가 false를 리턴하면, 다음에 state가 바뀌기 전까지 render()가 완전히 호출되지 않고 넘어갑니다. componentWillUpdatecomponentDidUpdate 또한 호출되지 않습니다.

- -

기본적으로 shouldComponentUpdate는 항상 true를 리턴합니다. state가 제자리에서(in place) 바뀐 경우에 발생하는 파악하기 힘든 버그를 막기 위함입니다. 하지만 state가 항상 변경 불가능하도록 주의하고 render()에서 propsstate를 읽기만 하면 이전 props 및 state와 바뀌는 값을 비교하는 shouldComponentUpdate를 직접 구현할 수 있습니다.

- -

성능에 병목이 있다면, 특히 컴포넌트가 매우 많은 경우 shouldComponentUpdate를 사용하여 앱을 빠르게 만들 수 있습니다.

-

업데이트 시: componentWillUpdate #

void componentWillUpdate(
-  object nextProps, object nextState
-)
-
-

새로운 props나 state를 받았을 때 렌더링 직전에 호출됩니다. 최초 렌더링 시에는 호출되지 않습니다.

- -

업데이트가 일어나기 전에 준비하기 위해 사용할 수 있습니다.

- -
-

주의:

- -

이 메소드에서는 this.setState()를 호출할 수 없습니다. prop 변화에 반응하여 state를 업데이트해야 할 경우, componentWillReceiveProps를 대신 사용하세요.

-
-

업데이트 시: componentDidUpdate #

void componentDidUpdate(
-  object prevProps, object prevState
-)
-
-

컴포넌트의 업데이트가 DOM에 반영된 직후에 호출됩니다. 최초 렌더링 시에는 호출되지 않습니다.

- -

컴포넌트가 업데이트된 뒤 DOM을 조작해야 하는 경우 사용할 수 있습니다.

-

마운트 해제 시: componentWillUnmount #

void componentWillUnmount()
-
-

컴포넌트가 DOM에서 마운트 해제 되기 직전에 호출됩니다.

- -

이 메소드에서 타이머를 무효화하거나 componentDidMount에서 만들어진 DOM 엘리먼트를 정리하는 등 필요한 정리 작업을 수행할 수 있습니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-specs-zh-CN.html b/docs/component-specs-zh-CN.html deleted file mode 100644 index 70954878c1..0000000000 --- a/docs/component-specs-zh-CN.html +++ /dev/null @@ -1,625 +0,0 @@ - - - - - - - 组件的规范和生命周期 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 组件的规范和生命周期 -

-
- -

组件规范(Specifications) #

-

当调用 React.createClass() 创建一个组件类时,你应该提供一个包含有 render 方法以及可选的其他生命周期方法的 规范(Specifications)对象.

- -
-

注意:

- -

同样可以使用单纯的 JavaScript 类作为组件类. 这些类可以实现大多数相同的方法,虽然有一些不同.更多关于不同的信息,请阅读我们关于ES6 classes的文档.

-
-

render #

ReactElement render()
-
-

render() 是必须的

- -

当被调用时,它应该检查 this.propsthis.state 并返回单个子元素.这个子元素即可以是一个 对原生DOM的虚拟表达(比如 <div />React.DOM.div())也可以是其他你自定义的复合组件.

- -

你也可以返回 nullfalse 来指示你不想要任何东西被渲染.幕后,React 渲染一个 <noscript> tag 来与我们当前的diffing算法协同工作.当返回 nullfalse ,ReactDOM.findDOMNode(this) 会返回 null.

- -

render() 函数应该是纯净的,意味着它不改变组件的状态,它在每次调用时返回相同的结果,并且它不读和写 DOM 或者其他方式与浏览器互动(例如,使用 setTimeout).如果你需要与浏览器互动,在 componentDidMount() 里执行你的工作,或者其他生命周期方法里.保持 render() 纯净使服务器渲染更实用并且让组件更容易被思考.

- -

### getInitialState

-
object getInitialState()
-
-

当组件被挂载时调用一次.返回值会被用作为 this.state 的初始值.

- -
-

注意:

- -

这个方法在从 React.Component 扩展的 ES6 class 组件里不可用。 更多的信息,请阅读我们关于ES6 classes的文档.

-
-

getDefaultProps #

object getDefaultProps()
-
-

在类被创建时调用一次并被缓存.在这个mapping里的值会被设置给 this.props 如果父组件没有指定对应的 prop (例如 使用一个 in 检查).

- -

这个方法在任何实例被创建之前调用,因此不能依赖于 this.props.另外,小心,任何被 getDefaultProps()返回的复杂对象会被跨实例共享,而不是被拷贝.

-

propTypes #

object propTypes
-
-

propTypes 对象允许你验证传递到你的组建的 props.更多关于 propTypes 的信息,见 Reusable Components.

-

mixins #

array mixins
-
-

mixins 数组允许你用 mixins 来在多个组件间共享行为.更多关于 mixins 的信息,见 Reusable Components.

-

statics #

object statics
-
-

statics 对象允许你定义可以在组件类上调用的静态方法.例如:

-
var MyComponent = React.createClass({
-  statics: {
-    customMethod: function(foo) {
-      return foo === 'bar';
-    }
-  },
-  render: function() {
-  }
-});
-
-MyComponent.customMethod('bar');  // true
-
-

在这个块里定义的方法是 static,意味着你可以在任何组件实例被创建前运行他们,并且这些方法没有对你组件的 props 或 state 的访问权.如果你在静态方法里检查props的值,把调用者作为参数传入props给静态函数.

-

displayName #

string displayName
-
-

displayName 字符串被用在调试信息.JSX 自动设置这个值;见 JSX in Depth.

-

Lifecycle Methods #

-

多种方法在组件生命周期的特定点上被执行.

-

Mounting: componentWillMount #

void componentWillMount()
-
-

被调用一次,即在客户端也在服务端,在最初的渲染发生之前 立即被调用.如果你在这个方法里调用 setState , render() 将会看到更新的 state 并不论state的变化只执行一次.

-

Mounting: componentDidMount #

void componentDidMount()
-
-

被调用一次,只在客户端(不在服务端),在最初的渲染发生之后 立即被调用.在生命周期的这个点上,你可以访问任何对你的子级的refs (比如 访问底层的DOM表达).子组件的 componentDidMount() 方法在父组件之前被调用.

- -

如果你想与其他 JavaScript 框架整合,用 setTimeoutsetInterval 设置timers,或者发送 AJAX 请求,执行这些操作在此方法中.

-

Updating: componentWillReceiveProps #

void componentWillReceiveProps(
-  object nextProps
-)
-
-

当一个组件收到新的props时被调用.这个方法不会为最初的渲染调用.

- -

使用它作为响应 prop 转换的时机(在render() 被用 this.setState() 更新state调用 之前) .旧的 props 可以通过 this.props 访问. 在这个函数里调用 this.setState() 不会触发任何额外的渲染.

-
componentWillReceiveProps: function(nextProps) {
-  this.setState({
-    likesIncreasing: nextProps.likeCount > this.props.likeCount
-  });
-}
-
-
-

注意:

- -

并没有类似的 componentWillReceiveState 方法. 一个即将到来的 prop 转变可能会导致一个 state 变化,但是反之不是. 如果你需要实现一个对 state 变化相应的操作,使用 componentWillUpdate.

-
-

Updating: shouldComponentUpdate #

boolean shouldComponentUpdate(
-  object nextProps, object nextState
-)
-
-

当新的props或者state被收到,在渲染前被调用.这个方法不会在最初的渲染或者 forceUpdate 时被调用.

- -

使用此方法作为一个 return false 的时机,当你确定新的 props 和 state 的转换不需要组件更新时.

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return nextProps.id !== this.props.id;
-}
-
-

如果 shouldComponentUpdate 返回false, render() 会在下次state变化前被完全跳过. 另外,componentWillUpdatecomponentDidUpdate 将不会被调用.

- -

默认情况下, shouldComponentUpdate 总是返回 true 来阻止当 state 突变时的细微bug,但是如果你仔细的把 state 作为不变量对待并只从 render()里的 propsstate读,你就可以用一个比较旧的props和state与他们的替换者的实现来重写 shouldComponentUpdate.

- -

如果性能是瓶颈,尤其是随着成百上千的组件,使用 shouldComponentUpdate 来加速你的app.

-

Updating: componentWillUpdate #

void componentWillUpdate(
-  object nextProps, object nextState
-)
-
-

当新的props或者state被接受时,在渲染前被立即调用.这个方法不会被初始渲染调用.

- -

使用这个方法作为 在更新发生前执行一些准备 的时机.

- -
-

Note:

- -

不能 在这个方法里使用 this.setState() .如果你需要响应一个prop变化来更新state,使用 componentWillReceiveProps 来替代.

-
-

Updating: componentDidUpdate #

void componentDidUpdate(
-  object prevProps, object prevState
-)
-
-

在组件的更新被刷新到DOM后立即被调用.这个方法不会被初始渲染调用.

- -

使用这个方法作为 当组件被更新后在DOM上操作 的时机.

-

Unmounting: componentWillUnmount #

void componentWillUnmount()
-
-

在组件被从DOM卸载 前 被立即调用.

- -

在这个方法里执行一些必要的清理操作,比如无效化 timers 或者清理任何被 componentDidMount 创建的DOM元素.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/component-specs.html b/docs/component-specs.html deleted file mode 100644 index 23c9a4ea43..0000000000 --- a/docs/component-specs.html +++ /dev/null @@ -1,625 +0,0 @@ - - - - - - - Component Specs and Lifecycle | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Component Specs and Lifecycle -

-
- -

Component Specifications #

-

When creating a component class by invoking React.createClass(), you should provide a specification object that contains a render method and can optionally contain other lifecycle methods described here.

- -
-

Note:

- -

It is also possible to use plain JavaScript classes as component classes. These classes can implement most of the same methods, though there are some differences. For more information about these differences, please read our documentation about ES6 classes.

-
-

render #

ReactElement render()
-
-

The render() method is required.

- -

When called, it should examine this.props and this.state and return a single child element. This child element can be either a virtual representation of a native DOM component (such as <div /> or React.DOM.div()) or another composite component that you've defined yourself.

- -

You can also return null or false to indicate that you don't want anything rendered. Behind the scenes, React renders a <noscript> tag to work with our current diffing algorithm. When returning null or false, ReactDOM.findDOMNode(this) will return null.

- -

The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it's invoked, and it does not read from or write to the DOM or otherwise interact with the browser (e.g., by using setTimeout). If you need to interact with the browser, perform your work in componentDidMount() or the other lifecycle methods instead. Keeping render() pure makes server rendering more practical and makes components easier to think about.

-

getInitialState #

object getInitialState()
-
-

Invoked once before the component is mounted. The return value will be used as the initial value of this.state.

- -
-

Note:

- -

This method is not available on ES6 class components that extend React.Component. For more information, please read our documentation about ES6 classes.

-
-

getDefaultProps #

object getDefaultProps()
-
-

Invoked once and cached when the class is created. Values in the mapping will be set on this.props if that prop is not specified by the parent component (i.e. using an in check).

- -

This method is invoked before any instances are created and thus cannot rely on this.props. In addition, be aware that any complex objects returned by getDefaultProps() will be shared across instances, not copied.

-

propTypes #

object propTypes
-
-

The propTypes object allows you to validate props being passed to your components. For more information about propTypes, see Reusable Components.

-

mixins #

array mixins
-
-

The mixins array allows you to use mixins to share behavior among multiple components. For more information about mixins, see Reusable Components.

-

statics #

object statics
-
-

The statics object allows you to define static methods that can be called on the component class. For example:

-
var MyComponent = React.createClass({
-  statics: {
-    customMethod: function(foo) {
-      return foo === 'bar';
-    }
-  },
-  render: function() {
-  }
-});
-
-MyComponent.customMethod('bar');  // true
-
-

Methods defined within this block are static, meaning that you can run them before any component instances are created, and the methods do not have access to the props or state of your components. If you want to check the value of props in a static method, have the caller pass in the props as an argument to the static method.

-

displayName #

string displayName
-
-

The displayName string is used in debugging messages. JSX sets this value automatically; see JSX in Depth.

-

Lifecycle Methods #

-

Various methods are executed at specific points in a component's lifecycle.

-

Mounting: componentWillMount #

void componentWillMount()
-
-

Invoked once, both on the client and server, immediately before the initial rendering occurs. If you call setState within this method, render() will see the updated state and will be executed only once despite the state change.

-

Mounting: componentDidMount #

void componentDidMount()
-
-

Invoked once, only on the client (not on the server), immediately after the initial rendering occurs. At this point in the lifecycle, you can access any refs to your children (e.g., to access the underlying DOM representation). The componentDidMount() method of child components is invoked before that of parent components.

- -

If you want to integrate with other JavaScript frameworks, set timers using setTimeout or setInterval, or send AJAX requests, perform those operations in this method.

-

Updating: componentWillReceiveProps #

void componentWillReceiveProps(
-  object nextProps
-)
-
-

Invoked when a component is receiving new props. This method is not called for the initial render.

- -

Use this as an opportunity to react to a prop transition before render() is called by updating the state using this.setState(). The old props can be accessed via this.props. Calling this.setState() within this function will not trigger an additional render.

-
componentWillReceiveProps: function(nextProps) {
-  this.setState({
-    likesIncreasing: nextProps.likeCount > this.props.likeCount
-  });
-}
-
-
-

Note:

- -

One common mistake is for code executed during this lifecycle method to assume that props have changed. To understand why this is invalid, read A implies B does not imply B implies A

- -

There is no analogous method componentWillReceiveState. An incoming prop transition may cause a state change, but the opposite is not true. If you need to perform operations in response to a state change, use componentWillUpdate.

-
-

Updating: shouldComponentUpdate #

boolean shouldComponentUpdate(
-  object nextProps, object nextState
-)
-
-

Invoked before rendering when new props or state are being received. This method is not called for the initial render or when forceUpdate is used.

- -

Use this as an opportunity to return false when you're certain that the transition to the new props and state will not require a component update.

-
shouldComponentUpdate: function(nextProps, nextState) {
-  return nextProps.id !== this.props.id;
-}
-
-

If shouldComponentUpdate returns false, then render() will be completely skipped until the next state change. In addition, componentWillUpdate and componentDidUpdate will not be called.

- -

By default, shouldComponentUpdate always returns true to prevent subtle bugs when state is mutated in place, but if you are careful to always treat state as immutable and to read only from props and state in render() then you can override shouldComponentUpdate with an implementation that compares the old props and state to their replacements.

- -

If performance is a bottleneck, especially with dozens or hundreds of components, use shouldComponentUpdate to speed up your app.

-

Updating: componentWillUpdate #

void componentWillUpdate(
-  object nextProps, object nextState
-)
-
-

Invoked immediately before rendering when new props or state are being received. This method is not called for the initial render.

- -

Use this as an opportunity to perform preparation before an update occurs.

- -
-

Note:

- -

You cannot use this.setState() in this method. If you need to update state in response to a prop change, use componentWillReceiveProps instead.

-
-

Updating: componentDidUpdate #

void componentDidUpdate(
-  object prevProps, object prevState
-)
-
-

Invoked immediately after the component's updates are flushed to the DOM. This method is not called for the initial render.

- -

Use this as an opportunity to operate on the DOM when the component has been updated.

-

Unmounting: componentWillUnmount #

void componentWillUnmount()
-
-

Invoked immediately before a component is unmounted from the DOM.

- -

Perform any necessary cleanup in this method, such as invalidating timers or cleaning up any DOM elements that were created in componentDidMount.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/components-and-props.html b/docs/components-and-props.html new file mode 100644 index 0000000000..808899a6d8 --- /dev/null +++ b/docs/components-and-props.html @@ -0,0 +1,606 @@ + + + + + + + + + Components and Props - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Components and Props +

+
+ +

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.

+ +

Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called "props") and return React elements describing what should appear on the screen.

+

Functional and Class Components #

+

The simplest way to define a component is to write a JavaScript function:

+
function Welcome(props) {
+  return <h1>Hello, {props.name}</h1>;
+}
+
+

This function is a valid React component because it accepts a single "props" object argument with data and returns a React element. We call such components "functional" because they are literally JavaScript functions.

+ +

You can also use an ES6 class to define a component:

+
class Welcome extends React.Component {
+  render() {
+    return <h1>Hello, {this.props.name}</h1>;
+  }
+}
+
+

The above two components are equivalent from React's point of view.

+ +

Classes have some additional features that we will discuss in the next sections. Until then, we will use functional components for their conciseness.

+

Rendering a Component #

+

Previously, we only encountered React elements that represent DOM tags:

+
const element = <div />;
+
+

However, elements can also represent user-defined components:

+
const element = <Welcome name="Sara" />;
+
+

When React sees an element representing a user-defined component, it passes JSX attributes to this component as a single object. We call this object "props".

+ +

For example, this code renders "Hello, Sara" on the page:

+
function Welcome(props) {
+  return <h1>Hello, {props.name}</h1>;
+}
+
+const element = <Welcome name="Sara" />;
+ReactDOM.render(
+  element,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

Let's recap what happens in this example:

+ +
    +
  1. We call ReactDOM.render() with the <Welcome name="Sara" /> element.
  2. +
  3. React calls the Welcome component with {name: 'Sara'} as the props.
  4. +
  5. Our Welcome component returns a <h1>Hello, Sara</h1> element as the result.
  6. +
  7. React DOM efficiently updates the DOM to match <h1>Hello, Sara</h1>.
  8. +
+ +
+

Caveat:

+ +

Always start component names with a capital letter.

+ +

For example, <div /> represents a DOM tag, but <Welcome /> represents a component and requires Welcome to be in scope.

+
+

Composing Components #

+

Components can refer to other components in their output. This lets us use the same component abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components.

+ +

For example, we can create an App component that renders Welcome many times:

+
function Welcome(props) {
+  return <h1>Hello, {props.name}</h1>;
+}
+
+function App() {
+  return (
+    <div>
+      <Welcome name="Sara" />
+      <Welcome name="Cahal" />
+      <Welcome name="Edite" />
+    </div>
+  );
+}
+
+ReactDOM.render(
+  <App />,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

Typically, new React apps have a single App component at the very top. However, if you integrate React into an existing app, you might start bottom-up with a small component like Button and gradually work your way to the top of the view hierarchy.

+ +
+

Caveat:

+ +

Components must return a single root element. This is why we added a <div> to contain all the <Welcome /> elements.

+
+

Extracting Components #

+

Don't be afraid to split components into smaller components.

+ +

For example, consider this Comment component:

+
function Comment(props) {
+  return (
+    <div className="Comment">
+      <div className="UserInfo">
+        <img className="Avatar"
+             src={props.author.avatarUrl}
+             alt={props.author.name} />
+        <div className="UserInfo-name">
+          {props.author.name}
+        </div>
+      </div>
+      <div className="Comment-text">
+        {props.text}
+      </div>
+      <div className="Comment-date">
+        {formatDate(props.date)}
+      </div>
+    </div>
+  );
+}
+
+

Try it on CodePen.

+ +

It accepts author (an object), text (a string), and date (a date) as props, and describes a comment on a social media website.

+ +

This component can be tricky to change because of all the nesting, and it is also hard to reuse individual parts of it. Let's extract a few components from it.

+ +

First, we will extract Avatar:

+
function Avatar(props) {
+  return (
+    <img className="Avatar"
+         src={props.user.avatarUrl}
+         alt={props.user.name} />
+  );
+}
+
+

The Avatar doesn't need to know that it is being rendered inside a Comment. This is why we have given its prop a more generic name: user rather than author.

+ +

We recommend naming props from the component's own point of view rather than the context in which it is being used.

+ +

We can now simplify Comment a tiny bit:

+
function Comment(props) {
+  return (
+    <div className="Comment">
+      <div className="UserInfo">
+        <Avatar user={props.author} />
+        <div className="UserInfo-name">
+          {props.author.name}
+        </div>
+      </div>
+      <div className="Comment-text">
+        {props.text}
+      </div>
+      <div className="Comment-date">
+        {formatDate(props.date)}
+      </div>
+    </div>
+  );
+}
+
+

Next, we will extract a UserInfo component that renders an Avatar next to user's name:

+
function UserInfo(props) {
+  return (
+    <div className="UserInfo">
+      <Avatar user={props.user} />
+      <div className="UserInfo-name">
+        {props.user.name}
+      </div>
+    </div>
+  );
+}
+
+

This lets us simplify Comment even further:

+
function Comment(props) {
+  return (
+    <div className="Comment">
+      <UserInfo user={props.author} />
+      <div className="Comment-text">
+        {props.text}
+      </div>
+      <div className="Comment-date">
+        {formatDate(props.date)}
+      </div>
+    </div>
+  );
+}
+
+

Try it on CodePen.

+ +

Extracting components might seem like grunt work at first, but having a palette of reusable components pays off in larger apps. A good rule of thumb is that if a part of your UI is used several times (Button, Panel, Avatar), or is complex enough on its own (App, FeedStory, Comment), it is a good candidate to be a reusable component.

+

Props are Read-Only #

+

Whether you declare a component as a function or a class, it must never modify its own props. Consider this sum function:

+
function sum(a, b) {
+  return a + b;
+}
+
+

Such functions are called "pure" because they do not attempt to change their inputs, and always return the same result for the same inputs.

+ +

In contrast, this function is impure because it changes its own input:

+
function withdraw(account, amount) {
+  account.total -= amount;
+}
+
+

React is pretty flexible but it has a single strict rule:

+ +

All React components must act like pure functions with respect to their props.

+ +

Of course, application UIs are dynamic and change over time. In the next section, we will introduce a new concept of "state". State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/composition-vs-inheritance.html b/docs/composition-vs-inheritance.html new file mode 100644 index 0000000000..15814f1921 --- /dev/null +++ b/docs/composition-vs-inheritance.html @@ -0,0 +1,544 @@ + + + + + + + + + Composition vs Inheritance - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Composition vs Inheritance +

+
+ +

React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components.

+ +

In this section, we will consider a few problems where developers new to React often reach for inheritance, and show how we can solve them with composition.

+

Containment #

+

Some components don't know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic "boxes".

+ +

We recommend that such components use the special children prop to pass children elements directly into their output:

+
function FancyBorder(props) {
+  return (
+    <div className={'FancyBorder FancyBorder-' + props.color}>
+      {props.children}
+    </div>
+  );
+}
+
+

This lets other components pass arbitrary children to them by nesting the JSX:

+
function WelcomeDialog() {
+  return (
+    <FancyBorder color="blue">
+      <h1 className="Dialog-title">
+        Welcome
+      </h1>
+      <p className="Dialog-message">
+        Thank you for visiting our spacecraft!
+      </p>
+    </FancyBorder>
+  );
+}
+
+

Try it on CodePen.

+ +

Anything inside the <FancyBorder> JSX tag gets passed into the FancyBorder component as a children prop. Since FancyBorder renders {props.children} inside a <div>, the passed elements appear in the final output.

+ +

While this is less common, sometimes you might need multiple "holes" in a component. In such cases you may come up with your own convention instead of using children:

+
function SplitPane(props) {
+  return (
+    <div className="SplitPane">
+      <div className="SplitPane-left">
+        {props.left}
+      </div>
+      <div className="SplitPane-right">
+        {props.right}
+      </div>
+    </div>
+  );
+}
+
+function App() {
+  return (
+    <SplitPane
+      left={
+        <Contacts />
+      }
+      right={
+        <Chat />
+      } />
+  );
+}
+
+

Try it on CodePen.

+ +

React elements like <Contacts /> and <Chat /> are just objects, so you can pass them as props like any other data.

+

Specialization #

+

Sometimes we think about components as being "special cases" of other components. For example, we might say that a WelcomeDialog is a special case of Dialog.

+ +

In React, this is also achieved by composition, where a more "specific" component renders a more "generic" one and configures it with props:

+
function Dialog(props) {
+  return (
+    <FancyBorder color="blue">
+      <h1 className="Dialog-title">
+        {props.title}
+      </h1>
+      <p className="Dialog-message">
+        {props.message}
+      </p>
+    </FancyBorder>
+  );
+}
+
+function WelcomeDialog() {
+  return (
+    <Dialog
+      title="Welcome"
+      message="Thank you for visiting our spacecraft!" />
+  );
+}
+
+

Try it on CodePen.

+ +

Composition works equally well for components defined as classes:

+
function 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: ''};
+  }
+
+  render() {
+    return (
+      <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>
+    );
+  }
+
+  handleChange(e) {
+    this.setState({login: e.target.value});
+  }
+
+  handleSignUp() {
+    alert(`Welcome aboard, ${this.state.login}!`);
+  }
+}
+
+

Try it on CodePen.

+

So What About Inheritance? #

+

At Facebook, we use React in thousands of components, and we haven't found any use cases where we would recommend creating component inheritance hierarchies.

+ +

Props and composition give you all the flexibility you need to customize a component's look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions.

+ +

If you want to reuse non-UI functionality between components, we suggest extracting it into a separate JavaScript module. The components may import it and use that function, object, or a class, without extending it.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/conditional-rendering.html b/docs/conditional-rendering.html new file mode 100644 index 0000000000..3ee738cf57 --- /dev/null +++ b/docs/conditional-rendering.html @@ -0,0 +1,603 @@ + + + + + + + + + Conditional Rendering - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Conditional Rendering +

+
+ +

In React, you can create distinct components that encapsulate behavior you need. Then, you can render only some of them, depending on the state of your application.

+ +

Conditional rendering in React works the same way conditions work in JavaScript. Use JavaScript operators like if or the conditional operator to create elements representing the current state, and let React update the UI to match them.

+ +

Consider these two components:

+
function UserGreeting(props) {
+  return <h1>Welcome back!</h1>;
+}
+
+function GuestGreeting(props) {
+  return <h1>Please sign up.</h1>;
+}
+
+

We'll create a Greeting component that displays either of these components depending on whether a user is logged in:

+
function Greeting(props) {
+  const isLoggedIn = props.isLoggedIn;
+  if (isLoggedIn) {
+    return <UserGreeting />;
+  } else {
+    return <GuestGreeting />;
+  }
+}
+
+ReactDOM.render(
+  // Try changing to isLoggedIn={true}:
+  <Greeting isLoggedIn={false} />,
+  document.getElementById('root')
+);
+
+

Try it out on CodePen.

+ +

This example renders a different greeting depending on the value of isLoggedIn prop.

+

Element Variables #

+

You can use variables to store elements. This can help you conditionally render a part of the component while the rest of the output doesn't change.

+ +

Consider these two new components representing Logout and Login buttons:

+
function LoginButton(props) {
+  return (
+    <button onClick={props.onClick}>
+      Login
+    </button>
+  );
+}
+
+function LogoutButton(props) {
+  return (
+    <button onClick={props.onClick}>
+      Logout
+    </button>
+  );
+}
+
+

In the example below, we will create a stateful component called LoginControl.

+ +

It will render either <LoginButton /> or <LogoutButton /> depending on its current state. It will also render a <Greeting /> from the previous example:

+
class LoginControl extends React.Component {
+  constructor(props) {
+    super(props);
+    this.handleLoginClick = this.handleLoginClick.bind(this);
+    this.handleLogoutClick = this.handleLogoutClick.bind(this);
+    this.state = {isLoggedIn: false};
+  }
+
+  handleLoginClick() {
+    this.setState({isLoggedIn: true});
+  }
+
+  handleLogoutClick() {
+    this.setState({isLoggedIn: false});
+  }
+
+  render() {
+    const isLoggedIn = this.state.isLoggedIn;
+
+    let button = null;
+    if (isLoggedIn) {
+      button = <LogoutButton onClick={this.handleLogoutClick} />;
+    } else {
+      button = <LoginButton onClick={this.handleLoginClick} />;
+    }
+
+    return (
+      <div>
+        <Greeting isLoggedIn={isLoggedIn} />
+        {button}
+      </div>
+    );
+  }
+}
+
+ReactDOM.render(
+  <LoginControl />,
+  document.getElementById('root')
+);
+
+

Try it out on CodePen.

+ +

While declaring a variable and using an if statement is a fine way to conditionally render a component, sometimes you might want to use a shorter syntax. There are a few ways to inline conditions in JSX, explained below.

+

Inline If with Logical && Operator #

+

You may embed any expressions in JSX by wrapping them in curly braces. This includes the JavaScript logical && operator. It can be handy for conditionally including an element:

+
function Mailbox(props) {
+  const unreadMessages = props.unreadMessages;
+  return (
+    <div>
+      <h1>Hello!</h1>
+      {unreadMessages.length > 0 &&
+        <h2>
+          You have {unreadMessages.length} unread messages.
+        </h2>
+      }
+    </div>
+  );
+}
+
+const messages = ['React', 'Re: React', 'Re:Re: React'];
+ReactDOM.render(
+  <Mailbox unreadMessages={messages} />,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

It works because in JavaScript, true && expression always evaluates to expression, and false && expression always evaluates to false.

+ +

Therefore, if the condition is true, the element right after && will appear in the output. If it is false, React will ignore and skip it.

+

Inline If-Else with Conditional Operator #

+

Another method for conditionally rendering elements inline is to use the JavaScript conditional operator condition ? true : false.

+ +

In the example below, we use it to conditionally render a small block of text.

+
render() {
+  const isLoggedIn = this.state.isLoggedIn;
+  return (
+    <div>
+      The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
+    </div>
+  );
+}
+
+

It can also be used for larger expressions although it is less obvious what's going on:

+
render() {
+  const isLoggedIn = this.state.isLoggedIn;
+  return (
+    <div>
+      {isLoggedIn ? (
+        <LogoutButton onClick={this.handleLogoutClick} />
+      ) : (
+        <LoginButton onClick={this.handleLoginClick} />
+      )}
+    </div>
+  );
+}
+
+

Just like in JavaScript, it is up to you to choose an appropriate style based on what you and your team consider more readable. Also remember that whenever conditions become too complex, it might be a good time to extract a component.

+

Preventing Component from Rendering #

+

In rare cases you might want a component to hide itself even though it was rendered by another component. To do this return null instead of its render output.

+ +

In the example below, the <WarningBanner /> is rendered depending on the value of the prop called warn. If the value of the prop is false, then the component does not render:

+
function WarningBanner(props) {
+  if (!props.warn) {
+    return null;
+  }
+
+  return (
+    <div className="warning">
+      Warning!
+    </div>
+  );
+}
+
+class Page extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {showWarning: true}
+    this.handleToggleClick = this.handleToggleClick.bind(this);
+  }
+
+  handleToggleClick() {
+    this.setState(prevState => ({
+      showWarning: !prevState.showWarning
+    }));
+  }
+
+  render() {
+    return (
+      <div>
+        <WarningBanner warn={this.state.showWarning} />
+        <button onClick={this.handleToggleClick}>
+          {this.state.showWarning ? 'Hide' : 'Show'}
+        </button>
+      </div>
+    );
+  }
+}
+
+ReactDOM.render(
+  <Page />,
+  document.getElementById('root')
+);
+
+

Try it out on CodePen.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/conferences-it-IT.html b/docs/conferences-it-IT.html index 88a8a3695e..342c19f829 100644 --- a/docs/conferences-it-IT.html +++ b/docs/conferences-it-IT.html @@ -1,12 +1,14 @@ + + - Conferenze | React - - + Conferenze - React + + @@ -44,67 +46,81 @@
- - - -
- -
+ +
+ +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Conferences -

-
- -

React.js Conf 2015 #

-

January 28 & 29 in Facebook HQ, CA

- -

Website - Schedule - Videos

- - -

ReactEurope 2015 #

-

July 2 & 3 in Paris, France

- -

Website - Schedule - Videos

-

Reactive 2015 #

-

November 2-4 in Bratislava, Slovakia

- -

Website - Schedule

-

React.js Conf 2016 #

-

February 22 & 23 in San Francisco, CA

- -

Website - Schedule - Videos

-

React Amsterdam 2016 #

-

April 16 in Amsterdam, The Netherlands

- -

Website - Videos

-

ReactEurope 2016 #

-

June 2 & 3 in Paris, France

- -

Website - Schedule

-

ReactRally 2016 #

-

August 25-26 in Salt Lake City, UT

- -

Website - Schedule - Videos

-

ReactNext 2016 #

-

September 15 in Tel Aviv, Israel

- -

Website - Schedule

-

ReactNL 2016 #

-

October 13 in Amsterdam, The Netherlands

- -

Website

-

Reactive 2016 #

-

October 26-28 in Bratislava, Slovakia

- -

Website

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/context-ko-KR.html b/docs/context-ko-KR.html deleted file mode 100644 index ef478bf8b9..0000000000 --- a/docs/context-ko-KR.html +++ /dev/null @@ -1,634 +0,0 @@ - - - - - - - 컨텍스트 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 컨텍스트 -

-
- -

React의 가장 큰 장점 중 하나는 React 컴포넌트를 통해 데이터의 흐름을 추적하기 쉽다는 것입니다. 컴포넌트를 보면 각각의 프로퍼티가 어떻게 전달되었는지 쉽게 파악할 수 있습니다.

- -

때때로 컴포넌트 트리를 통해 props을 전단하는 대신 수동으로 모든 레벨에서 데이터를 전달하고 싶은 경우가 있습니다. React의 "컨텍스트" 기능은 이를 가능하게 해줍니다.

- -
-

주의:

- -

컨텍스트는 실험적인 고급 기능입니다. 향후 릴리즈에서 API가 변경될 수 있습니다.

- -

대부분은 애플리켄이션은 컨텍스트가 필요하지 않을겁니다. 특히 React로 시작한 경우에는 컨텍스트를 사용하지 않을겁니다. 컨텍스트의 사용은 데이터 흐름을 명확하지 않게 만들기 때문에 코드를 이해하기 어려워 집니다. 이는 마치 앱에서 전역 변수를 state로 전달하는 경우와 유사합니다.

- -

만약 컨텍스트를 사용해야 하는 경우에도, 가능한 아껴 사용하세요.

- -

구축하는것이 애플리케이션이든 라이브러리든간에, 가능한 컨텍스트의 사용은 작은 영역으로 격리하고 직접적으로 컨텍스트 API를 사용하는 것을 피하세요. 그렇게 하면 API가 변경 되더라도 쉽게 업데이트 할 수 있습니다.

-
-

트리를 통해 정보를 자동으로 전달하기 #

-

아래와 같은 구조가 있다고 가정해 봅시다:

-
var Button = React.createClass({
-  render: function() {
-    return (
-      <button style={{background: this.props.color}}>
-        {this.props.children}
-      </button>
-    );
-  }
-});
-
-var Message = React.createClass({
-  render: function() {
-    return (
-      <div>
-        {this.props.text} <Button color={this.props.color}>삭제</Button>
-      </div>
-    );
-  }
-});
-
-var MessageList = React.createClass({
-  render: function() {
-    var color = "purple";
-    var children = this.props.messages.map(function(message) {
-      return <Message text={message.text} color={color} />;
-    });
-    return <div>{children}</div>;
-  }
-});
-
-

이 예제에서, 우리는 스타일을 주기 위해 수동으로 적절하게 ButtonMessages 컴포넌트에 color 프로퍼티를 엮어서 전달했습니다. 테마는 서브트리가 정보 조각의 일부(여기선 color)에 접근하기 원하는 좋은 예제입니다. 컨텍스트를 사용하면 우리는 이를 자동으로 트리로 전달할 수 있습니다:

-
var Button = React.createClass({
-  contextTypes: {
-    color: React.PropTypes.string
-  },
-  render: function() {
-    return (
-      <button style={{background: this.context.color}}>
-        {this.props.children}
-      </button>
-    );
-  }
-});
-
-var Message = React.createClass({
-  render: function() {
-    return (
-      <div>
-        {this.props.text} <Button>Delete</Button>
-      </div>
-    );
-  }
-});
-
-var MessageList = React.createClass({
-  childContextTypes: {
-    color: React.PropTypes.string
-  },
-  getChildContext: function() {
-    return {color: "purple"};
-  },
-  render: function() {
-    var children = this.props.messages.map(function(message) {
-      return <Message text={message.text} />;
-    });
-    return <div>{children}</div>;
-  }
-});
-
-

childContextTypesgetChildContextMessageList(context provider)에 추가함으로써, React는 정보를 자동으로 아래로 전달하며 서브트리내의 어떤 컴포넌트든 (여기선 Button) contextTypes를 정의함으로써 이에 접근할 수 있습니다.

- -

contextTypes가 정의되지 않은 경우, this.context는 빈 오브젝트가 됩니다.

-

부모-자식 커플링 #

-

컨텍스트는 다음과 같은 API를 구성할 수 있게 해줍니다:

-
<Menu>
-  <MenuItem>가지</MenuItem>
-  <MenuItem>땅콩호박</MenuItem>
-  <MenuItem>클레멘타인</MenuItem>
-</Menu>
-
-

Menu 컴포넌트에서 관련 정보를 전달함으로써 각각의 MenuItem가 부모인 Menu 컴포넌트와 통신할 수 있습니다.

- -

이 API를 이용해 컴포넌트를 구성하기 전에, 깔끔한 대안이 있는지 먼저 고려해 보세요. 다음과 같이 간단히 아이템을 배열로 넘겨 보겠습니다:

-
<Menu items={['가지', '땅콩호박', '클레멘타인']} />
-
-

원한다면 전체 React 컴포넌트를 프로퍼티로 전달할 수도 있습니다.

-

Referencing context in lifecycle methods #

-

If contextTypes is defined within a component, the following lifecycle methods will receive an additional parameter, the context object:

-
void componentWillReceiveProps(
-  object nextProps, object nextContext
-)
-
-boolean shouldComponentUpdate(
-  object nextProps, object nextState, object nextContext
-)
-
-void componentWillUpdate(
-  object nextProps, object nextState, object nextContext
-)
-
-void componentDidUpdate(
-  object prevProps, object prevState, object prevContext
-)
-

Referencing context in stateless functional components #

-

Stateless functional components are also able to reference context if contextTypes is defined as a property of the function. The following code shows the Button component above written as a stateless functional component.

-
function Button(props, context) {
-  return (
-    <button style={{background: context.color}}>
-      {props.children}
-    </button>
-  );
-}
-Button.contextTypes = {color: React.PropTypes.string};
-

컨텍스트를 사용하지 말아야 하는 경우 #

-

대부분의 경우, 깔끔한 코드를 위해 전역 변수를 피하는 것과 마찬가지로 컨텍스트의 사용을 피해야 합니다. 특히 "타이핑을 줄이거나" 명시적인 프로퍼티 전달 대신 이를 사용하려는 경우 다시 한번 생각해 보세요.

- -

컨텍스트의 가장 적절한 사용 사례는 로그인한 유저, 언어 설정, 테마 정보 등을 암시적으로 전달하는 것입니다. 컨텍스트를 사용함으로써 이런 정보들을 전역으로 다루는 대신 단일 React 서브트리 내에서 다룰 수 있습니다.

- -

모델 데이터를 컴포넌트로 전달하는데 컨텍스트를 사용하지 마세요. 트리를 통해 명시적으로 데이터를 엮어 전달하는 것이 훨씬 이해하기 쉽습니다. 컨텍스트는 렌더되는 위치에 따라 다르게 작동하기 때문에 컴포넌트를 더욱 연결되고(coupled) 재사용성이 떨어지게 만듭니다.

-

알려진 한계점 #

-

컴포넌트에 의해 제공되는 컨텍스트의 값이 변경될 때, 중간 부모가 shouldComponentUpdate에서false을 반환한다면 그 값을 사용하는 자손은 업데이트되지 않습니다. 자세한 내용은 #2517 이슈를 확인하세요.

- - -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/context-zh-CN.html b/docs/context-zh-CN.html deleted file mode 100644 index c2d487918d..0000000000 --- a/docs/context-zh-CN.html +++ /dev/null @@ -1,661 +0,0 @@ - - - - - - - Context | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Context -

-
- -

React优势之一是你可以很容易地从React组件里跟踪数据流动。当你查看一个组件时,你可以很容易地判断出传入了哪些props,而这也有利于你的App进行逻辑推断。

- -

有时,你想不通过在每一级组件设置prop的方式来向组件树内传递数据。那么,React的"context"特性可以让你做到这点。

- -
-

注意:

- -

Context是一个先进的实验性特性,这个API很可能在未来版本变化。

- -

大多数应用将不会需要用到context。尤其是如果你刚开始用React,你很可能不会想用它。使用context将会使你的代码难以理解,因为它让数据流变得不清晰。它类似于在你的应用里用以传递state的全局变量。

- -

如果你必须使用context,请保守地使用它。

- -

不论你正在创建一个应用或者是库,试着缩小context的使用范围,并尽可能避免直接使用context相关API,以便在API变动时容易升级。

-
-

在组件树内自动传递info #

-

假设你有一个这样的结构:

-
var Button = React.createClass({
-  render: function() {
-    return (
-      <button style={{background: this.props.color}}>
-        {this.props.children}
-      </button>
-    );
-  }
-});
-
-var Message = React.createClass({
-  render: function() {
-    return (
-      <div>
-        {this.props.text} <Button color={this.props.color}>Delete</Button>
-      </div>
-    );
-  }
-});
-
-var MessageList = React.createClass({
-  render: function() {
-    var color = "purple";
-    var children = this.props.messages.map(function(message) {
-      return <Message text={message.text} color={color} />;
-    });
-    return <div>{children}</div>;
-  }
-});
-
-

在这个例子里,我们手工传递一个叫color的prop,以便于给ButtonMessage组件添加合适的样式。当你想所有子组件可以访问一部分信息时(比如color),上面的设置主题是一个很好的例子。通过使用context,我们能自动在组件树中传递信息:

-
var Button = React.createClass({
-  contextTypes: {
-    color: React.PropTypes.string
-  },
-  render: function() {
-    return (
-      <button style={{background: this.context.color}}>
-        {this.props.children}
-      </button>
-    );
-  }
-});
-
-var Message = React.createClass({
-  render: function() {
-    return (
-      <div>
-        {this.props.text} <Button>Delete</Button>
-      </div>
-    );
-  }
-});
-
-var MessageList = React.createClass({
-  childContextTypes: {
-    color: React.PropTypes.string
-  },
-  getChildContext: function() {
-    return {color: "purple"};
-  },
-  render: function() {
-    var children = this.props.messages.map(function(message) {
-      return <Message text={message.text} />;
-    });
-    return <div>{children}</div>;
-  }
-});
-
-

通过添加childContextTypesgetChildContextMessageList(context提供者),React会自动下传信息,并且通过定义contextTypes,子树中的任何组件(在这个例子中,子组件是Button)可以访问context

- -

如果contextTypes没有定义,那么this.context将是一个空对象。

-

父子耦合 #

-

Context同样可以使你构建这样的API:

-
<Menu>
-  <MenuItem>aubergine</MenuItem>
-  <MenuItem>butternut squash</MenuItem>
-  <MenuItem>clementine</MenuItem>
-</Menu>
-
-

通过在Menu组件内下传相关的信息,每个MenuItem 可以与包含他们的Menu组件沟通。

- -

在你用这个API构建组件以前,考虑一下是否有清晰的替代方案 我们喜欢用数组传递items,就像下面这样:

-
<Menu items={['aubergine', 'butternut squash', 'clementine']} />
-
-

记住,如果你愿意,你同样可以在props里传递整个React组件。

-

在生命周期方法里引用context #

-

如果contextTypes是定义在一个组件中,接下来的生命周期方法会收到一个额外的参数,context对象:

-
void componentWillReceiveProps(
-  object nextProps, object nextContext
-)
-
-boolean shouldComponentUpdate(
-  object nextProps, object nextState, object nextContext
-)
-
-void componentWillUpdate(
-  object nextProps, object nextState, object nextContext
-)
-
-void componentDidUpdate(
-  object prevProps, object prevState, object prevContext
-)
-

在无状态函数组件里引用 context #

-

如果 contextTypes 被定义为函数的属性,无状态函数同样能够引用context。下面的代码展示了被写为无状态函数组件的Button组件:

-
function Button(props, context) {
-  return (
-    <button style={{background: context.color}}>
-      {props.children}
-    </button>
-  );
-}
-Button.contextTypes = {color: React.PropTypes.string};
-

更新context #

-

当state或props改变时,会调用getChildContext方法。为了能更新context内的数据,需要使用this.setState来触发组件state更新。这将会触发一个新的context,并且子组件也能接收变化。

-
var MediaQuery = React.createClass({
-  getInitialState: function(){
-    return {type:'desktop'};
-  },
-  childContextTypes: {
-    type: React.PropTypes.string
-  },
-  getChildContext: function() {
-    return {type: this.state.type};
-  },
-  componentDidMount: function(){
-    var checkMediaQuery = function(){
-      var type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
-      if (type !== this.state.type){
-        this.setState({type:type});
-      }
-    };
-
-    window.addEventListener('resize', checkMediaQuery);
-    checkMediaQuery();
-  },
-  render: function(){
-    return this.props.children;
-  }
-});
-

什么时候不用 context #

-

正如在写清晰代码时最好要避免使用全局变量一样,在大多数情况下,你应该避免使用context。特别是,在用它来"节省输入"和代替显式传入props时要三思。

- -

隐式传入登录的用户,当前的语言,或者主题信息,是context最好的使用场景。要不然所有这些可能就是全局变量,但是context让你限定他们到一个单独的React树里。

- -

在组件里传递你的模型数据时,不要依赖context。在组件树内显式传递数据,会更容易令人理解。之所以使用context会增加组件耦合度以及降低复用性,是因为组件在不同的地方渲染时,他们会表现出不同的行为。

-

已知的限制 #

-

假设由父组件提供的context值发生变动,但中间父级组件的shouldComponentUpdate返回了false,那么后代子级不会更新context。详见 issue #2517

- - -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/context.html b/docs/context.html index 56964562e7..fcebe56c41 100644 --- a/docs/context.html +++ b/docs/context.html @@ -1,12 +1,14 @@ + + - Context | React - - + Context - React + + @@ -44,421 +46,53 @@
- - - -
- + + +
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Frammenti con Chiave -

-
- -

In molti casi, puoi utilizzare la proprietà key per specificare chiavi sugli elementi che restituisci da render. Tuttavia, questo approccio fallisce in una situazione: se hai due insiemi di figli che devi riordinare, non esiste alcun modo di assegnare una chiave a ciascuno di essi senza aggiungere un elemento contenitore.

- -

Ovvero, se hai un componente come il seguente:

-
var Swapper = React.createClass({
-  propTypes: {
-    // `leftChildren` e `rightChildren` possono essere una stringa, un elemento, un array, etc.
-    leftChildren: React.PropTypes.node,
-    rightChildren: React.PropTypes.node,
-
-    swapped: React.PropTypes.bool
-  }
-  render: function() {
-    var children;
-    if (this.props.swapped) {
-      children = [this.props.rightChildren, this.props.leftChildren];
-    } else {
-      children = [this.props.leftChildren, this.props.rightChildren];
-    }
-    return <div>{children}</div>;
-  }
-});
-
-

I figli saranno smontati e rimontati nel momento in cui cambi la proprietà swapped poiché non ci sono chiavi che marcano i due insiemi di figli.

- -

Per risolvere questo problema, puoi utilizzare React.addons.createFragment per dare una chiave a ciascun insieme di figli.

-

ReactFragment React.addons.createFragment(object children) #

-

Anziché creare array, scriviamo:

-
if (this.props.swapped) {
-  children = React.addons.createFragment({
-    right: this.props.rightChildren,
-    left: this.props.leftChildren
-  });
-} else {
-  children = React.addons.createFragment({
-    left: this.props.leftChildren,
-    right: this.props.rightChildren
-  });
-}
-
-

Le chiavi degli oggetti passati (ovvero, left e right) sono usate come chiavi per l'intero insieme di figli, e l'ordine delle chiavi dell'oggetto è utilizzato per determinare l'ordine dei figli visualizzati. Con questo cambiamento, i due insiemi di figli saranno correttamente riordinati nel DOM senza bisogno di smontaggio.

- -

Il valore di ritorno di createFragment deve essere trattato come un oggetto opaco; puoi usare gli helper React.Children per iterare su un frammento ma non dovresti accedervi direttamente. Nota anche che ci stiamo affidando al motore JavaScript per preservare l'ordine dell'enumerazione degli oggetti, che non viene garantito dalla specifica ma è implementato dai principali browser e macchine virtuali per oggetti con chiavi non numeriche.

- -
-

Nota:

- -

In un futuro, createFragment potrebbe essere sostituito da una API quale

-
return (
-  <div>
-    <x:frag key="right">{this.props.rightChildren}</x:frag>,
-    <x:frag key="left">{this.props.leftChildren}</x:frag>
-  </div>
-);
-
-

che ti permette di assegnare chiavi direttamente in JSX senza aggiungere elementi contenitore.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/create-fragment-ja-JP.html b/docs/create-fragment-ja-JP.html deleted file mode 100644 index 44d45b5541..0000000000 --- a/docs/create-fragment-ja-JP.html +++ /dev/null @@ -1,553 +0,0 @@ - - - - - - - キー付けされたフラグメント | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- キー付けされたフラグメント -

-
- -

多くの場合、 render から返された要素のキーを特定するために、 key プロパティを使用します。しかし、以下のような特定の状況では、こういったことを行うことはできません。何度も並び替える必要のある2つの子要素を持っているときには、ラッパーの要素を加える以外にそれぞれのセットのキーを追加する方法はありません。

- -

これは、以下のようなコンポーネントがある場合には、

-
var Swapper = React.createClass({
-  propTypes: {
-    // `leftChildren` と `rightChildren` は文字列や、要素や、配列などになり得ます。
-    leftChildren: React.PropTypes.node,
-    rightChildren: React.PropTypes.node,
-
-    swapped: React.PropTypes.bool
-  }
-  render: function() {
-    var children;
-    if (this.props.swapped) {
-      children = [this.props.rightChildren, this.props.leftChildren];
-    } else {
-      children = [this.props.leftChildren, this.props.rightChildren];
-    }
-    return <div>{children}</div>;
-  }
-});
-
-

2つの子要素のセットを表すキーがないため、 swapped プロパティを変更するたびに子要素はアンマウントされ、再度マウントされます。

- -

この問題を解決するために、子要素のセットのキーを与える React.addons.createFragment を使用することができます。

-

ReactFragment React.addons.createFragment(object children) #

-

配列を作成する代わりに、以下のように記述することができます。

-
if (this.props.swapped) {
-  children = React.addons.createFragment({
-    right: this.props.rightChildren,
-    left: this.props.leftChildren
-  });
-} else {
-  children = React.addons.createFragment({
-    left: this.props.leftChildren,
-    right: this.props.rightChildren
-  });
-}
-
-

渡されたオブジェクトのキー(leftright のことです)は子要素のセット全体のキーとして使用され、そのオブジェクトのキーの順序はレンダリングされた子要素の順序を決める際に使用されます。この変更により、2つの子要素のセットはアンマウントされることなく、DOMの中で適切に順序立てられます。

- -

createFragment の戻り値は、不透明なオブジェクトとして扱われるべきです。つまり、 React.Children ヘルパーを、フラグメントのなかでループするために使用することはできますが、直接アクセスするべきではないということです。私たちはいまオブジェクトの一覧における順序を保存するのにJavaScriptのエンジンに頼っていることに注意してください。それは、仕様が保証されているわけではありませんが、数に関するものではないキーとオブジェクトは全てのメジャーなブラウザやVMで実行されます。

- -
-

注意: -将来、 createFragment は以下のようなAPIに変わるでしょう。

-
return (
-  <div>
-    <x:frag key="right">{this.props.rightChildren}</x:frag>,
-    <x:frag key="left">{this.props.leftChildren}</x:frag>
-  </div>
-);
-
-

ラッパーの要素を加えることなく、JSXの中に直接キーをアサインすることができます。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/create-fragment-ko-KR.html b/docs/create-fragment-ko-KR.html deleted file mode 100644 index df11a5361d..0000000000 --- a/docs/create-fragment-ko-KR.html +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - 키가 할당된 프래그먼트 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 키가 할당된 프래그먼트 -

-
- -

대부분의 경우는 key prop으로 render에서 반환된 엘리먼트에 키를 명시할 수 있습니다. 하지만 말썽을 부리는 경우가 한가지 있습니다: 재정렬을 할 두개의 자식 집합을 가지고 있는 경우, 감싸는 엘리먼트 없이 각각의 집합에 키를 부여하는 것은 불가능 합니다.

- -

이 말은, 만약 다음과 같은 컴포넌트가 있다면:

-
var Swapper = React.createClass({
-  propTypes: {
-    // `leftChildren`과 `rightChildren`은 문자열, 엘리먼트, 배열 혹은 다른 무언가 일 수 있음.
-    leftChildren: React.PropTypes.node,
-    rightChildren: React.PropTypes.node,
-
-    swapped: React.PropTypes.bool
-  },
-  render: function() {
-    var children;
-    if (this.props.swapped) {
-      children = [this.props.rightChildren, this.props.leftChildren];
-    } else {
-      children = [this.props.leftChildren, this.props.rightChildren];
-    }
-    return <div>{children}</div>;
-  }
-});
-
-

swapped prop을 변경할 경우 자식은 마운트 해제되거나 다시 마운트 될 수 있습니다. 두 자식 집합에 키가 할당되지 않았기 때문입니다.

- -

이 문제를 해결하기 위해서 createFragment를 사용해 자식 집합에 키를 부여할 수 있습니다.

-

Array<ReactNode> createFragment(object children) #

-

배열을 만드는 대신에 다음과 같이 해볼 수 있습니다:

-
var createFragment = require('react-addons-create-fragment');
-
-if (this.props.swapped) {
-  children = createFragment({
-    right: this.props.rightChildren,
-    left: this.props.leftChildren
-  });
-} else {
-  children = createFragment({
-    left: this.props.leftChildren,
-    right: this.props.rightChildren
-  });
-}
-
-

전달된 객체의 키(left, right)는 모든 자식 집합의 키로 사용됩니다. 그리고 객체에서 키들의 순서는 렌더된 자식들의 순서를 결정하는데 사용됩니다. 이러한 변경으로 두 자식 집합은 언마운팅하지 않고도 DOM에서 적절하게 재정렬 됩니다.

- -

createFragment의 반환값은 불명확한 객체로 취급되어야 합니다; React.Children 헬퍼를 사용해 프래그먼트를 순환할 수 있지만 직접 접근해서는 안됩니다. 명세에는 없지만 모든 주요 브라우저와 VM들에서 JavaScript 엔진이 숫자가 아닌 키에 대해서도 객체 목록 순서를 보존한다는 점을 주의하세요.

- -
-

주의:

- -

미래에 createFragment는 대략 다음과 같은 API로 교체될 것입니다

-
return (
-  <div>
-    <x:frag key="right">{this.props.rightChildren}</x:frag>,
-    <x:frag key="left">{this.props.leftChildren}</x:frag>
-  </div>
-);
-
-

JSX에서 엘리먼트로 감싸지 않고도 key를 바로 선언할 수 있게 될 것입니다.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/create-fragment-zh-CN.html b/docs/create-fragment-zh-CN.html deleted file mode 100644 index 3016ae1719..0000000000 --- a/docs/create-fragment-zh-CN.html +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - Keyed Fragments | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Keyed Fragments -

-
- -

在大多数情况下,你可以使用 key prop 指定你从 render 返回的元素的 keys。然而,这在一个情况下会失败:如果你有两组你需要记录的子级,将没有办法在不使用包裹元素的情况下放置一个 key 到每组上。

- -

即是,如果你有一个像这样的组件:

-
var Swapper = React.createClass({
-  propTypes: {
-    // `leftChildren` and `rightChildren` can be a string, element, array, etc.
-    leftChildren: React.PropTypes.node,
-    rightChildren: React.PropTypes.node,
-
-    swapped: React.PropTypes.bool
-  },
-  render: function() {
-    var children;
-    if (this.props.swapped) {
-      children = [this.props.rightChildren, this.props.leftChildren];
-    } else {
-      children = [this.props.leftChildren, this.props.rightChildren];
-    }
-    return <div>{children}</div>;
-  }
-});
-
-

这些子级会在当你改变 swapped prop 时加载和卸载,因为没有任何的 key 标记在这两组子级上。

- -

要解决这个问题,你可以使用 createFragment 插件来给予这两组子级 keys.

-

Array<ReactNode> createFragment(object children) #

-

代替创建数组,我们这样写:

-
var createFragment = require('react-addons-create-fragment');
-
-if (this.props.swapped) {
-  children = createFragment({
-    right: this.props.rightChildren,
-    left: this.props.leftChildren
-  });
-} else {
-  children = createFragment({
-    left: this.props.leftChildren,
-    right: this.props.rightChildren
-  });
-}
-
-

被传入对象的 keys (即 leftright)被用作为整组子级的 keys,并且对象 keys 的顺序被用于决定渲染子级的顺序。通过这个改变,这两个子级将会恰当的在 DOM 里排序,而不被卸载。

- -

createFragment 的返回值应该被对待为一个不透明的对象;你可以使用 React.Children 来遍历一个 fragment 但是不应该直接访问它。同样注意,我们依赖于 JavaScript 引擎保留了对象的枚举顺序,这点在 spec 上是不保证的,但是所有主要的浏览器和 VMs 都对非数字键的对象实现了这个特性。

- -
-

注意:

- -

将来,createFragment 也许会被替换为如下的API:

-
return (
-  <div>
-    <x:frag key="right">{this.props.rightChildren}</x:frag>,
-    <x:frag key="left">{this.props.leftChildren}</x:frag>
-  </div>
-);
-
-

允许你直接在 JSX 里赋值 keys 而不用添加包裹元素。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/create-fragment.html b/docs/create-fragment.html index e2bc07d7e5..b1bb8d8a82 100644 --- a/docs/create-fragment.html +++ b/docs/create-fragment.html @@ -1,12 +1,14 @@ + + - Keyed Fragments | React - - + Keyed Fragments - React + + @@ -44,406 +46,44 @@
- - - -
- -
+ +
+ +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Visualizzare Dati -

-
- -

L'attività più basilare che puoi effettuare con una UI è mostrare dei dati. React rende visualizzare dati semplice e mantiene automaticamente l'interfaccia aggiornata quando i dati cambiano.

-

Per Cominciare #

-

Diamo un'occhiata ad un esempio davvero semplice. Creiamo un file dal nome hello-react.html con il codice seguente:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-
-      // ** Il tuo codice va qui! **
-
-    </script>
-  </body>
-</html>
-
-

Nel resto della documentazione, ci concentreremo soltanto sul codice JavaScript e assumeremo che sia inserito in un modello come quello qui sopra. Sostituisci il commento segnaposto qui sopra con il seguente codice JSX:

-
var HelloWorld = React.createClass({
-  render: function() {
-    return (
-      <p>
-        Ciao, <input type="text" placeholder="Scrivi il tuo nome" />!
-        È il {this.props.date.toTimeString()}
-      </p>
-    );
-  }
-});
-
-setInterval(function() {
-  ReactDOM.render(
-    <HelloWorld date={new Date()} />,
-    document.getElementById('example')
-  );
-}, 500);
-

Aggiornamenti Reattivi #

-

Apri hello-react.html in un browser web e scrivi il tuo nome nel campo di testo. Osserva che React cambia soltanto la stringa di testo dell'ora nella UI — ogni input che inserisci nel campo di testo rimane, anche se non hai scritto alcun codice che gestisce questo comportamento. React lo capisce da solo al tuo posto e fa la cosa giusta.

- -

La maniera in cui siamo in grado di capirlo è che React non manipola il DOM a meno che non sia necessario. Utilizza un DOM interno fittizio e veloce per effettuare confronti ed effettuare le mutazioni del DOM più efficienti al tuo posto.

- -

Gli input di questo componente sono chiamati props — breve per "properties". Sono passati come attributi nella sintassi JSX. Puoi pensare ad essi come immutabili nel contesto del componente, ovvero, non assegnare mai this.props.

-

I Componenti Sono Come Funzioni #

-

I componenti React sono molto semplici. Puoi immaginarli come semplici funzioni che ricevono in ingresso props e state (discusso in seguito) e rendono HTML. Fatta questa premessa, i componenti sono molto semplici da descrivere.

- -
-

Nota:

- -

Una limitazione: i componenti React possono rendere soltanto un singolo nodo radice. Se desideri restituire nodi multipli, essi devono essere avvolti in un singolo nodo radice.

-
-

Sintassi JSX #

-

Crediamo fermamente che i componenti sono la maniera corretta di separare i concetti anziché i "modelli" e la "logica di presentazione." Pensiamo che il markup e il codice che lo genera siano intimamente collegati. Inoltre, la logica di presentazione è solitamente molto complessa e usare un linguaggio di modello per esprimerla risulta dispendioso.

- -

Abbiamo scoperto che la migliore soluzione a questo problema è generare HTML e un albero di componenti direttamente dal codice JavaScript in maniera da poter utilizzare tutta la potenza espressiva di un vero linguaggio di programmazione per costruire UI.

- -

Per rendere il compito più facile, abbiamo aggiunto una semplice e opzionale sintassi simile all'HTML per creare questi nodi di albero React.

- -

JSX ti permette di creare oggetti JavaScript usando una sintassi HTML. Per generare un collegamento in React usando puro JavaScript puoi scrivere:

- -

React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Ciao!')

- -

Con JSX ciò diventa:

- -

<a href="https://facebook.github.io/react/">Ciao!</a>

- -

Abbiamo scoperto che questo ha reso la costruzione di applicazioni React più semplice e i designer tendono a preferire la sintassi, ma ciascuno ha un diverso flusso di lavoro, quindi JSX non è richiesto per utilizzare React.

- -

JSX è di dimensioni contenute. Per maggiori informazioni, consulta JSX in profondità. Oppure osserva la trasformazione in tempo reale sulla REPL di Babel.

- -

JSX è simile all'HTML, ma non proprio identico. Consulta la guida JSX gotchas per alcune differenze fondamentali.

- -

Babel offre una varietà di strumenti per cominciare a usare JSX, dagli strumenti a riga di comando alle integrazioni in Ruby on Rails. Scegli lo strumento che funziona meglio per te.

-

React senza JSX #

-

JSX è completamente opzionale; non è necessario utilizzare JSX con React. Puoi creare elementi React in puro JavaScript usando React.createElement, che richiede un nome di tag o di componente, un oggetto di proprietà e un numero variabile di argomenti che rappresentano nodi figli opzionali.

-
var child1 = React.createElement('li', null, 'Primo Contenuto di Testo');
-var child2 = React.createElement('li', null, 'Secondo Contenuto di Testo');
-var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
-ReactDOM.render(root, document.getElementById('example'));
-
-

Per comodità, puoi creare funzioni factory scorciatoia per costruire elementi da componenti personalizzati.

-
var Factory = React.createFactory(ComponentClass);
-...
-var root = Factory({ custom: 'prop' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React possiede già delle factory predefinite per i tag HTML comuni:

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Contenuto di Testo')
-           );
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/displaying-data-ja-JP.html b/docs/displaying-data-ja-JP.html deleted file mode 100644 index ba71c56195..0000000000 --- a/docs/displaying-data-ja-JP.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - データを表示する | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- データを表示する -

-
- -

UIについて、最も基本的なことは、いくつかのデータを表示することです。Reactはデータを表示し、変更された時にはインターフェースを最新の状態に自動的に保つことが簡単にできるようになっています。

-

はじめに #

-

本当に単純な例を見てみましょう。hello-react.html ファイルを以下のようなコードで作成してください。

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-
-      // ** コードをここに書きます! **
-
-    </script>
-  </body>
-</html>
-
-

このドキュメントの中では、JavaScriptのコードにのみフォーカスします。そして、それが上のようなテンプレートに挿入されていると考えます。

-
var HelloWorld = React.createClass({
-  render: function() {
-    return (
-      <p>
-        Hello, <input type="text" placeholder="Your name here" />!
-        It is {this.props.date.toTimeString()}
-      </p>
-    );
-  }
-});
-
-setInterval(function() {
-  ReactDOM.render(
-    <HelloWorld date={new Date()} />,
-    document.getElementById('example')
-  );
-}, 500);
-

リアクティブなアップデート #

-

hello-react.html をウェブブラウザで開き、テキストフィールドにあなたの名前を入力してください。ReactはUIのうち、時間の文字列しか変更しないことに注意してください。あなたがテキストフィールドに入力したものは残っています。あなたはそういったコードを書いていないのにも関わらずです。Reactはあなたのことを理解しており、正しいことを行います。

- -

このことについて私たちが理解できる方法は、Reactは必要になるまで、DOMの操作を行わないということです。 Reactは、DOMの変化を表現し、あなたにもっとも効率的なDOMの変化を見積もるために早い、内部のモックのDOMを使っています。

- -

このコンポーネントのインプットは props と呼ばれるものです。"properties" の省略形です。それらはJSXシンタックスの中でアトリビュートとして渡されます。それらはコンポーネントの中で不変と考えるべきで、 this.props には書き込まないようにしてください

-

コンポーネントは関数のようなものです。 #

-

Reactのコンポーネントはとても単純です。それらは propsstate (後述します)を取り、HTMLをレンダリングする単純な関数だと考えることができます。この考えの元、コンポーネントは簡単に理解することができます。

- -
-

注意:

- -

1つの制限: Reactのコンポーネントは単一の最上位のノードだけをレンダリングします。複数のノードをリターンしたい場合は、単一の最上位のもので ラップする必要があります

-
-

JSXシンタックス #

-

私たちは関心を分離する正しい方法は「テンプレート」と「ディスプレイロジック」ではなくコンポーネントであると強く考えています。ビューを生成するマークアップとコードは密接につながっていると考えています。加えて、ディスプレイロジックはとても複雑になりえますし、ビューを表現するのにテンプレート言語を使うことはとてもややこしくなりえます。

- -

私たちは、この問題の最適解は、UIを構築するのにリアルなプログラミング言語の表現力の全てを使うことができるように、JavaScriptのコードからHTMLやコンポーネントのツリーを直接生成することだと発見しました。

- -

上記のことを簡単に行うために、私たちはReactのツリーノードを構築するためのとても単純で、 オプショナルな HTMLに似たシンタックスを加えました。

- -

JSXはHTMLのシンタックスを使ってJavaScriptのオブジェクトを構築するのを可能にします。 純粋にJavaScriptを使ってReactでリンクを構築するには、以下のように書きます。

- -

React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')

- -

JSXでは、以下のように変換されます。

- -

<a href="https://facebook.github.io/react/">Hello!</a>

- -

以上のようなことで、Reactのアプリを作成するのは簡単になりましたし、デザイナーはこのシンタックスを好むようになると発見しました。しかし、人は自分自身のワークフローを持っているものです。 JSXはReactを使う際に必ずしも必要ではありません。

- -

JSXはとても小さいです。さらに学ぶためには、JSXの深層を参照ください。または、ライブJSXコンパイラーで変換の動作を確認してください。

- -

JSXはHTMLに似ていますが、正確に同じではありません。いくつかのキーの違いについてはJSXの理解 をご覧ください。

- -

JSXを初めて使う際に最も簡単なのは、ブラウザで JSXTransformer を使う方法です。これはプロダクションでは使わないことを強くお勧めします。コードは、コマンドラインのreact-toolsパッケージを使うことでプリコンパイルできます。

-

JSXを使わないReact #

-

JSXは完全にオプションです。Reactと一緒にJSXを使う必要はありません。React.createElement を使って、ただのJavaScriptでReactの要素を作ることもできます。それは、タグの名前やコンポーネント、プロパティのオブジェクト、いくつかのオプションの子要素をとります。

-
var child1 = React.createElement('li', null, 'First Text Content');
-var child2 = React.createElement('li', null, 'Second Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
-ReactDOM.render(root, document.getElementById('example'));
-
-

便利に書くために、カスタムコンポーネントで要素を作るために簡略した記法でファクトリー関数を作ることができます。

-
var Factory = React.createFactory(ComponentClass);
-...
-var root = Factory({ custom: 'prop' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

Reactはすでに、共通なHTMLのタグについてはビルトインの関数を持っています。

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/displaying-data-ko-KR.html b/docs/displaying-data-ko-KR.html deleted file mode 100644 index d14f4b3b98..0000000000 --- a/docs/displaying-data-ko-KR.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - 데이터를 표시하기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 데이터를 표시하기 -

-
- -

UI를 가지고 할 수 있는 가장 기초적인 것은 데이터를 표시하는 것입니다. React는 데이터를 표시하고 데이터가 변할 때마다 인터페이스를 최신의 상태로 자동으로 유지하기 쉽게 해 줍니다.

-

시작하기 #

-

정말 간단한 예제를 보도록 하죠. 다음과 같은 코드의 hello-react.html 파일을 만듭시다.

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-
-      // ** 코드는 여기에 작성하면 됩니다! **
-
-    </script>
-  </body>
-</html>
-
-

문서의 나머지에서, 코드가 위와 같은 HTML 템플릿에 들어갔다고 가정하고 JavaScript 코드에만 집중할 것입니다. 위의 주석 부분을 다음과 같은 JSX 코드로 바꿔 보세요:

-
var HelloWorld = React.createClass({
-  render: function() {
-    return (
-      <p>
-        안녕, <input type="text" placeholder="이름을 여기에 작성하세요" />!
-        지금 시간은 {this.props.date.toTimeString()} 입니다.
-      </p>
-    );
-  }
-});
-
-setInterval(function() {
-  ReactDOM.render(
-    <HelloWorld date={new Date()} />,
-    document.getElementById('example')
-  );
-}, 500);
-

반응 적(Reactive) 업데이트 #

-

hello-react.html 파일을 웹 브라우저에서 열어 당신의 이름을 텍스트 필드에 써 보세요. React는 단지 시간을 표시하는 부분만을 바꿉니다 — 텍스트 필드 안에 입력한 것은 그대로 남아 있구요, 당신이 이 동작을 관리하는 그 어떤 코드도 쓰지 않았음에도 불구하고 말이죠. React는 그걸 올바른 방법으로 알아서 해줍니다.

- -

우리가 이걸 할 수 있었던 건, React는 필요한 경우에만 DOM을 조작하기 때문입니다. React는 빠른 React 내부의 DOM 모형을 이용하여 변경된 부분을 측정하고, 가장 효율적인 DOM 조작 방법을 계산해 줍니다.

- -

이 컴포넌트에 대한 입력은 props 라고 불립니다 — "properties" 를 줄인 것이죠. 그들은 JSX 문법에서는 어트리뷰트로서 전달됩니다. 당신은 props 를 컴포넌트 안에서 불변의(immutable) 엘리먼트로서 생각해야 하고, this.props 를 덮어씌우려고 해서는 안됩니다.

-

컴포넌트들은 함수와 같습니다 #

-

React 컴포넌트들은 매우 단순합니다. 당신은 그것들을 propsstate (이것들은 나중에 언급할 것입니다) 를 받고 HTML을 렌더링하는 단순한 함수들로 생각해도 됩니다. 이걸 염두하면, 컴포넌트의 작동을 이해하는 것도 쉽습니다.

- -
-

주의:

- -

한가지 제약이 있습니다: React 컴포넌트들은 단 하나의 루트 노드(root node)만을 렌더할 수 있습니다. 만약 여러개의 노드들을 리턴하고 싶다면, 그것들은 단 하나의 루트 노드로 싸여져 있어야만 합니다.

-
-

JSX 문법 #

-

우리는 컴포넌트를 사용하는 것이 "템플릿"과 "디스플레이 로직(display logic)"을 이용하는 것보다 관심을 분리(separate concerns)하는 데에 올바른 방법이라고 강하게 믿고 있습니다. 우리는 마크업과 그것을 만들어내는 코드는 친밀하게 함께 결합되어있다고 생각합니다. 또한, 디스플레이 로직은 종종 매우 복잡하고, 그것을 템플릿 언어를 이용해 표현하는 것은 점점 사용하기 어렵게 됩니다.

- -

우리는 이 문제를 해결하는 최고의 해결책은, UI를 만드는 진짜 프로그래밍 언어의 표현력을 모두 사용할 수 있는 JavaScript 코드로부터 HTML과 컴포넌트 트리들을 생성하는 것임을 발견했습니다.

- -

이것을 더 쉽게 하기 위해서, 우리는 매우 간단하고, 선택적인 HTML과 비슷한 문법을 추가하여 이 React 트리 노드들을 만들 수 있게 했습니다.

- -

JSX는 당신으로 하여금 HTML 문법을 이용해 JavaScript 객체를 만들게 해줍니다. React를 이용해 순수한 JavaScript 문법으로 링크를 만드려고 한다면, 코드는 다음과 같습니다:

- -

React.createElement('a', {href: 'https://facebook.github.io/react/'}, '안녕하세요!')

- -

JSX를 이용하면:

- -

<a href="https://facebook.github.io/react/">안녕하세요!</a>

- -

우리는 이것이 React 앱들을 만들기 쉽게 하고, 디자이너들이 이 문법을 더 선호하는 것을 발견했습니다, 하지만 모든 사람은 그들만의 선호하는 워크플로우가 있기 마련이므로, JSX는 React를 사용하기 위해 필수적이지는 않습니다.

- -

JSX는 매우 작은 언어입니다. 그것을 배우고 싶다면, JSX 깊게 살펴보기를 살펴 보시기 바랍니다. 또는, 바벨 REPL를 통해 문법이 변환되는 것을 살펴 보시기 바랍니다.

- -

JSX는 HTML과 비슷하지만, 완전히 똑같지는 않습니다. JSX의 실수하기 쉬운 부분들에 중요한 차이점들에 대해 설명되어 있습니다.

- -

바벨에서 JSX를 시작하는 여러 방법을 제공합니다. 여기에는 커맨드 라인 툴부터 루비 온 레일스 연동까지 다양한 방법이 있습니다. 가장 편한 툴을 사용하세요.

-

JSX 없이 React 사용하기 #

-

JSX는 완전히 선택적입니다. 당신은 React와 JSX를 함께 사용하지 않아도 상관없습니다. 그냥 JavaScript에서 React 엘리먼트를 React.createElement로 만들 수 있습니다. 여기에 태그 이름이나 컴포넌트, 속성 객체, 자식 엘리먼트들을 전달하면 됩니다.

-
var child1 = React.createElement('li', null, 'First Text Content');
-var child2 = React.createElement('li', null, 'Second Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
-ReactDOM.render(root, document.getElementById('example'));
-
-

편의를 위하여, 당신은 팩토리 함수 헬퍼들을 이용해 커스텀 컴포넌트로부터 엘리먼트들을 만들 수 있습니다.

-
var Factory = React.createFactory(ComponentClass);
-...
-var root = Factory({ custom: 'prop' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React는 이미 일반적인 HTML 태그에 대한 빌트인 팩토리를 가지고 있습니다.

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, '텍스트')
-           );
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/displaying-data-ru-RU.html b/docs/displaying-data-ru-RU.html deleted file mode 100644 index e9595ccb8f..0000000000 --- a/docs/displaying-data-ru-RU.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - Отображение данных | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Отображение данных -

-
- -

Главная задача интерфейса — это отображать данные. React делает это легко и обновляет интерфейс сразу, как только изменятся данные.

-

Начало #

-

Давайте рассмотрим простой пример. Создайте файл hello-react.html со следующим текстом:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-
-      // ** Ваш код будет здесь! **
-
-    </script>
-  </body>
-</html>
-
-

Добавим в этот шаблон немного JavaScript. Замените комментарий на следующий JSX-код:

-
var HelloWorld = React.createClass({
-  render: function() {
-    return (
-      <p>
-        Hello, <input type="text" placeholder="Your name here" />!
-        It is {this.props.date.toTimeString()}
-      </p>
-    );
-  }
-});
-
-setInterval(function() {
-  ReactDOM.render(
-    <HelloWorld date={new Date()} />,
-    document.getElementById('example')
-  );
-}, 500);
-

Реактивные обновления #

-

Откройте hello-react.html в браузере и введите в текстовое поле свое имя. Что происходит со страницей? Каждые полсекунды обновляется время, остальные же части страницы остаются без изменений. Обратите внимание, что мы не написали ни строчки кода, чтобы управлять этим поведением. React сам отлично понимает что надо делать и обновляет элементы на странице по мере необходимости.

- -

Суть в том, что React не меняет DOM-дерево до тех пор, пока это не потребуется. Чтобы отразить изменения, React использует быстрое внутреннее представление DOM-дерева и просчитывает как его изменить наиболее эффективно.

- -

Передаваемые в компонент данные называются props — сокращенно от "properties". В JSX коде они передаются как атрибуты компонента. Считайте, что компонент получает props только для чтения. Никогда не перезаписывайте значения this.props внутри компонента.

-

Компоненты как функции #

-

Компоненты React — довольно простые сущности. Можно считать их обыкновенными функциями, которые принимают на входе props и state (см. далее) и возвращают HTML. Если помнить об этом, то компоненты становятся простыми для понимания.

- -
-

Замечание:

- -

Есть одно ограничение: Компоненты React умеют возвращать только один узел. Если вам надо вернуть сразу несколько, они должны быть обернуты в один корневой узел.

-
-

Синтаксис JSX #

-

Мы убеждены, что компоненты — самый подходящий способ разделения ответственностей, гораздо более удобный чем "шаблоны" и "вынесение логики на страницу". Мы считаем, что разметка и код, который её генерирует, неотделимы друг от друга. Плюс, логика на странице часто бывает запутанной, и использование шаблонизаторов, чтобы описать её, только затрудняет работу.

- -

Мы решили, что лучшим вариантом будет генерировать HTML и деревья компонентов прямо из JS кода. Так вы сможете зайдействовать всю выразительную мощь современного языка программирования для создания интерфейсов.

- -

А чтобы упростить создание узлов дерева, мы ввели опциональный HTML-подобный синтаксис.

- -

JSX позволяет вам создавать JavaScript объекты используя синтаксис HTML. Для генерации ссылки в React вы напишете на чистом JavaScript:

- -

React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')

- -

С JSX это станет:

- -

<a href="https://facebook.github.io/react/">Hello!</a>

- -

Мы установили, что с JSX создавать React приложения проще, и дизайнеров как правило устраивает его синтаксис. Но у разных людей разные предпочтения, поэтому стоит сказать, что JSX необязателен при работе с React.

- -

JSX сам по себе очень прост. Чтобы узнать о нем больше, почитайте подробно про JSX. Или можете попробовать его в Babel REPL.

- -

JSX похож на HTML, но но имеет существенные отличия. Почитайте про подводные камни JSX, чтобы понять их ключевые различия.

- -

Babel предлагает несколько способов начать работу с JSX, от консольных утилит до интеграций с Ruby on Rails. Выберите тот инструмент, который лучше всего вам подходит.

-

React без использования JSX #

-

JSX полностью опционален; вам совсем необязательно использовать его вместе с React. Вы можете создавать React-элементы на чистом JavaScript используя функцию React.createElement, которая принимает имя тега или компонента, объект со свойствами, и набор необязательных дочерних элементов.

-
var child1 = React.createElement('li', null, 'First Text Content');
-var child2 = React.createElement('li', null, 'Second Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
-ReactDOM.render(root, document.getElementById('example'));
-
-

Для удобства, вы можете создать сокращенные фабричные функции, чтобы создавать React-элементы из ваших собственных компонентов.

-
var Factory = React.createFactory(ComponentClass);
-...
-var root = Factory({ custom: 'prop' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

А для базовых HTML тегов в React уже есть встроенные фабрики:

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/displaying-data-zh-CN.html b/docs/displaying-data-zh-CN.html deleted file mode 100644 index 5fc501416b..0000000000 --- a/docs/displaying-data-zh-CN.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - 显示数据 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 显示数据 -

-
- -

用户界面能做的最基础的事就是显示一些数据。React 让显示数据变得简单,当数据变化的时候,用户界面会自动同步更新。

-

开始 #

-

让我们看一个非常简单的例子。新建一个名为 hello-react.html 的文件,代码内容如下:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-
-      // ** 在这里替换成你的代码 **
-
-    </script>
-  </body>
-</html>
-
-

在接下去的文档中,我们只关注 JavaScript 代码,假设我们把代码插入到上面那个模板中。用下面的代码替换掉上面用来占位的注释。

-
var HelloWorld = React.createClass({
-  render: function() {
-    return (
-      <p>
-        Hello, <input type="text" placeholder="Your name here" />!
-        It is {this.props.date.toTimeString()}
-      </p>
-    );
-  }
-});
-
-setInterval(function() {
-  ReactDOM.render(
-    <HelloWorld date={new Date()} />,
-    document.getElementById('example')
-  );
-}, 500);
-

被动更新 (Reactive Updates) #

-

在浏览器中打开 hello-react.html ,在输入框输入你的名字。你会发现 React 在用户界面中只改变了时间, 任何你在输入框输入的内容一直保留着,即使你没有写任何代码来完成这个功能。React 为你解决了这个问题,做了正确的事。

- -

我们想到的方法是除非不得不操作 DOM ,React 是不会去操作 DOM 的。它用一种更快的内置仿造的 DOM 来操作差异,为你计算出出效率最高的 DOM 改变

- -

对这个组件的输入称为 props - "properties"的缩写。得益于 JSX 语法,它们通过参数传递。你必须知道在组件里,这些属性是不可改变的,也就是说 this.props 是只读的

-

组件就像是函数 #

-

React 组件非常简单。你可以认为它们就是简单的函数,接受 propsstate (后面会讨论) 作为参数,然后渲染出 HTML。正是应为它们是这么的简单,这使得它们非常容易理解。

- -
-

注意:

- -

只有一个限制: React 组件只能渲染单个根节点。如果你想要返回多个节点,它们必须被包含在同一个节点里。

-
-

JSX 语法 #

-

我们坚信组件是正确方法去做关注分离,而不是通过“模板”和“展示逻辑”。我们认为标签和生成它的代码是紧密相连的。此外,展示逻辑通常是很复杂的,通过模板语言实现这些逻辑会产生大量代码。

- -

我们得出解决这个问题最好的方案是通过 JavaScript 直接生成模板,这样你就可以用一个真正语言的所有表达能力去构建用户界面。

- -

为了使这变得更简单,我们做了一个非常简单、可选类似 HTML 语法 ,通过函数调用即可生成模板的编译器,称为 JSX。

- -

JSX 让你可以用 HTML 语法去写 JavaScript 函数调用 为了在 React 生成一个链接,通过纯 JavaScript 你可以这么写:

- -

React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello React!')

- -

通过 JSX 这就变成了

- -

<a href="https://facebook.github.io/react/">Hello React!</a>

- -

我们发现这会使搭建 React 应用更加简单,设计师也偏向用这用语法,但是每个人可以有它们自己的工作流,所以JSX 不是必须用的。

- -

JSX 非常小;上面“hello, world”的例子使用了 JSX 所有的特性。想要了解更多,请看 深入理解 JSX。或者直接使用在线 JSX 编译器观察变化过程。

- -

JSX 类似于 HTML,但不是完全一样。参考 JSX 陷阱 学习关键区别。

- -

[Babel 公开了一些使用 JSX 的方式],从命令行工具到 Ruby on Rails 集成。选择一个对你来说最合适的工具。

-

没有 JSX 的 React #

-

JSX完全是可选的;你无需在 React 中必须使用 JSX。你可以通过 React.createElement 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,第三个是子节点。

-
var child1 = React.createElement('li', null, 'First Text Content');
-var child2 = React.createElement('li', null, 'Second Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
-ReactDOM.render(root, document.getElementById('example'));
-
-

方便起见,你可以创建基于自定义组件的速记工厂方法。

-
var Factory = React.createFactory(ComponentClass);
-...
-var root = Factory({ custom: 'prop' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React 已经为 HTML 标签提供内置工厂方法。

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/displaying-data-zh-TW.html b/docs/displaying-data-zh-TW.html deleted file mode 100644 index a8624a7003..0000000000 --- a/docs/displaying-data-zh-TW.html +++ /dev/null @@ -1,592 +0,0 @@ - - - - - - - Displaying Data | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Displaying Data -

-
- -

在使用者介面所能做最基本的事情就是呈現資料. React讓呈現資料變得更加容易並且當資料有所變動時也能自動地讓使用者介面保持呈現最新的資料.

-

入門(Getting Started) #

-

我們從一個相當簡單的範例開始. 建立一個名為 hello-react.html 的檔案裡面包含下列程式碼:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-
-      // ** 將你的程式碼放在這裡! **
-
-    </script>
-  </body>
-</html>
-
-

這份文件其他部份,我們將只會專注在JavaScript程式碼解說上,並且假設程式碼會被放置在如上述模板的註解區塊內. 用下列的JSX程式碼取代上述註解區塊:

-
var HelloWorld = React.createClass({
-  render: function() {
-    return (
-      <p>
-        Hello, <input type="text" placeholder="Your name here" />!
-        It is {this.props.date.toTimeString()}
-      </p>
-    );
-  }
-});
-
-setInterval(function() {
-  ReactDOM.render(
-    <HelloWorld date={new Date()} />,
-    document.getElementById('example')
-  );
-}, 500);
-

反應性更新(Reactive Updates) #

-

在一個瀏覽器上開啟檔案 hello-react.html 並且在文字區塊填入你的名字. 請注意React僅僅改變UI上的時間字串 — 你在文字區塊輸入的任何文字依舊存在, 即使你並沒有寫任何程式碼來管理這個行為.React可以為你分辨出這樣的行為並且做出正確的回應.

- -

之所以能夠分辨出這樣的行為是因為React除非在真正有必要的情況下,否則不會對DOM做任何操作. 它使用一個快速的, 內部虛擬的DOM(internal mock DOM)來為你施行比較和計算最有效率的DOM變動(DOM mutation)

- -

輸入到元件(component)的內容我們稱為props — 是屬性("properties")的簡稱. 他們在JSX語法中作為傳遞屬性之用. 你應該把這些屬性當做元件中不可被改變的, 也就是說, 永遠不要對 this.props 做寫入的行為.

-

元件就是函數(Components are Just Like Functions) #

-

React元件(components)是非常簡單的. 你能把它們想成是簡單的函數帶入propsstate(後面會討論這部份)並且呈送給HTML(render HTML). 在心中保持住這個想法, 就能容易理解元件(components). -React components are very simple. You can think of them as simple functions that take in props and state (discussed later) and render HTML. With this in mind, components are easy to reason about.

- -
-

注意(Note):

- -

一個局限性: React元件(components)只能呈送(render)給一個單一根節點(root node). 如果你想要回傳多個節點(multiple nodes)他們必須被包裹在單一根節點內.

-
-

JSX語法 #

-

我們深信元件(components)才是分離關注點(separate concerns)的正確方法, 而並非傳統的模板("templates")和顯示邏輯("display logic")觀念. 我們認為標記(markup)和產生它的程式碼應當緊密的綁在一起. 另外, 顯示邏輯(display logic)常常是非常複雜的, 若使用模板語言(template languages)來詮釋它就顯得笨重或累贅.

- -

我們找到解決這個問題的最佳解答就是直接在JavaScript程式內產生HTML和元件樹(component trees)如此一來你就能使用真正的程式語言的表達能力(expressive power)來建立使用者介面(UIs).

- -

為了能更輕鬆實現, 我們增加了一個非常簡單, 可選擇性使用的 類似HTML的語法(HTML-like syntax) 來創建這些React樹節點(React tree nodes).

- -

JSX能讓你使用HTML語法來創建JavaScript物件. 在React裡使用純JavaScript來產生一個鏈接(link)你可以這樣寫:

- -

React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')

- -

使用JSX語法則變成:

- -

<a href="https://facebook.github.io/react/">Hello!</a>

- -

我們發現這麼做能讓建立React apps更加容易並且設計師往往喜歡語法, 但是每個人都有他們自己的工作流程, 所以在使用React時JSX並非必要.

- -

JSX非常簡單易懂. 若想要學習更多關於JSX, 請參閱 JSX in depth. 或是可以使用線上及時轉換工具 the Babel REPL.

- -

JSX類似於HTML, 但不盡然完全相同. 參閱 JSX gotchas 來比較一些主要的差異點.

- -

Babel exposes a number of ways to get started using JSX, 涵蓋從命令列工具到Ruby on Rails整合. 可以從中選擇最適合你的工具.

-

React不使用JSX的範例(React without JSX) #

-

JSX完全是可選擇性使用的; 你可以不拿JSX跟React一起使用. 你能在純粹的JavaScript環境中使用React.createElement來創建React元素(React elements), 它搭配一個標籤名(tag name)或是元件(component), 一個屬性物件(properties object), 和數個選擇性子參數(child arguments).

-
var child1 = React.createElement('li', null, 'First Text Content');
-var child2 = React.createElement('li', null, 'Second Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
-ReactDOM.render(root, document.getElementById('example'));
-
-

為了方便起見, 你能創建速記factory函式(short-hand factory functions)然後從自訂元件(custom components)建立元素(elements).

-
var Factory = React.createFactory(ComponentClass);
-...
-var root = Factory({ custom: 'prop' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

針對一般的HTML標籤React已經有內建的factories函式:

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/displaying-data.html b/docs/displaying-data.html index c4a639c6c8..e571433e38 100644 --- a/docs/displaying-data.html +++ b/docs/displaying-data.html @@ -1,593 +1,10 @@ - - - - - - Displaying Data | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Displaying Data -

-
- -

The most basic thing you can do with a UI is display some data. React makes it easy to display data and automatically keeps the interface up-to-date when the data changes.

-

Getting Started #

-

Let's look at a really simple example. Create a hello-react.html file with the following code:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-
-      // ** Your code goes here! **
-
-    </script>
-  </body>
-</html>
-
-

For the rest of the documentation, we'll just focus on the JavaScript code and assume it's inserted into a template like the one above. Replace the placeholder comment above with the following JSX:

-
class HelloWorld extends React.Component {
-  render() {
-    return (
-      <p>
-        Hello, <input type="text" placeholder="Your name here" />!
-        It is {this.props.date.toTimeString()}
-      </p>
-    );
-  }
-}
-
-function tick() {
-  ReactDOM.render(
-    <HelloWorld date={new Date()} />,
-    document.getElementById('example')
-  );
-}
-
-setInterval(tick, 500);
-

Reactive Updates #

-

Open hello-react.html in a web browser and type your name into the text field. Notice that React is only changing the time string in the UI — any input you put in the text field remains, even though you haven't written any code to manage this behavior. React figures it out for you and does the right thing.

- -

The way we are able to figure this out is that React does not manipulate the DOM unless it needs to. It uses a fast, internal mock DOM to perform diffs and computes the most efficient DOM mutation for you.

- -

The inputs to this component are called props — short for "properties". They're passed as attributes in JSX syntax. You should think of these as immutable within the component, that is, never write to this.props.

-

Components are Just Like Functions #

-

React components are very simple. You can think of them as simple functions that take in props and state (discussed later) and render HTML. With this in mind, components are easy to reason about.

- -
-

Note:

- -

One limitation: React components can only render a single root node. If you want to return multiple nodes they must be wrapped in a single root.

-
-

JSX Syntax #

-

We strongly believe that components are the right way to separate concerns rather than "templates" and "display logic." We think that markup and the code that generates it are intimately tied together. Additionally, display logic is often very complex and using template languages to express it becomes cumbersome.

- -

We've found that the best solution for this problem is to generate HTML and component trees directly from the JavaScript code such that you can use all of the expressive power of a real programming language to build UIs.

- -

In order to make this easier, we've added a very simple, optional HTML-like syntax to create these React tree nodes.

- -

JSX lets you create JavaScript objects using HTML syntax. To generate a link in React using pure JavaScript you'd write:

- -

React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')

- -

With JSX this becomes:

- -

<a href="https://facebook.github.io/react/">Hello!</a>

- -

We've found this has made building React apps easier and designers tend to prefer the syntax, but everyone has their own workflow, so JSX is not required to use React.

- -

JSX is very small. To learn more about it, see JSX in depth. Or see the transform in action in the Babel REPL.

- -

JSX is similar to HTML, but not exactly the same. See JSX gotchas for some key differences.

- -

Babel exposes a number of ways to get started using JSX, ranging from command line tools to Ruby on Rails integrations. Choose the tool that works best for you.

-

React without JSX #

-

JSX is completely optional; you don't have to use JSX with React. You can create React elements in plain JavaScript using React.createElement, which takes a tag name or component, a properties object, and variable number of optional child arguments.

-
var child1 = React.createElement('li', null, 'First Text Content');
-var child2 = React.createElement('li', null, 'Second Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
-ReactDOM.render(root, document.getElementById('example'));
-
-

For convenience, you can create short-hand factory functions to create elements from custom components.

-
var Factory = React.createFactory(ComponentClass);
-...
-var root = Factory({ custom: 'prop' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React already has built-in factories for common HTML tags:

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/dom-differences-it-IT.html b/docs/dom-differences-it-IT.html deleted file mode 100644 index 2c77080dda..0000000000 --- a/docs/dom-differences-it-IT.html +++ /dev/null @@ -1,507 +0,0 @@ - - - - - - - Differenze del DOM | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Differenze del DOM -

-
- -

React ha implementato eventi indipendenti dal browser e un sistema DOM per ragioni di prestazioni e compatibilità cross-browser. Abbiamo colto l'occasione di dare una ripulita ad alcuni aspetti trascurati nelle implementazioni del DOM nei browser.

- -
    -
  • Tutte le proprietà e attributi del DOM (incluso i gestori di eventi) dovrebbero essere camelCased per essere consistenti con lo stile standard JavaScript. Abbiamo intenzionalmente deviato dalla specifica perché la specifica stessa è inconsistente. Tuttavia, gli attributi data-* e aria-* sono conformi alle specifiche e dovrebbero essere soltanto in minuscolo.
  • -
  • L'attributo style accetta un oggetto JavaScript con proprietà camelCased anziché una stringa CSS. Questo è consistente con la proprietà DOM style di JavaScript, è più efficiente, e previene falle nella sicurezza XSS.
  • -
  • Tutti gli oggetti evento sono conformi con la specifica W3C, e tutti gli eventi (incluso il submit) si propagano correttamente secondo la specifica W3C. Consulta il Sistema degli Eventi per maggiori dettagli.
  • -
  • L'evento onChange si comporta come ti aspetteresti: questo evento è emesso ogni qualvolta il valore di un campo di un modulo cambia anziché, in maniera inconsistente, quando il campo perde il focus. Abbiamo intenzionalmente deviato dal comportamento corrente dei browser perché onChange è un nome incorretto per questo comportamento e React dipende dall'emissione di questo evento in tempo reale in risposta all'input dell'utente. Leggi Moduli per maggiori dettagli.
  • -
  • Attributi dei campi di modulo come value e checked, oppure textarea. Maggiori dettagli.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/dom-differences-ko-KR.html b/docs/dom-differences-ko-KR.html deleted file mode 100644 index c0b8a7a90a..0000000000 --- a/docs/dom-differences-ko-KR.html +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - - DOM과의 차이점 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- DOM과의 차이점 -

-
- -

React는 성능과 크로스 브라우저 호환성을 이유로 브라우저에 독립적인 이벤트와 DOM 시스템으로 구현되었습니다. 브라우저 DOM 구현의 일관성없는 부분들을 정리할 기회를 가졌습니다.

- -
    -
  • 모든 DOM 프로퍼티와 어트리뷰트는 (이벤트 핸들러를 포함해) 표준 JavaScript 스타일과 일치하도록 카멜케이스를 사용해야 합니다. 하지만, data-*aria-* 어트리뷰트는 사양을 준수해 소문자만 사용해야 합니다.
  • -
  • style 어트리뷰트는 CSS 문자열 대신에 카멜케이스로 된 프로퍼티를 가지는 JavaScript 객체를 받습니다. 이는 DOM style JavaScript 프로퍼티와 일치하면서도 좀 더 효율적이며, XSS 보안 취약점을 예방할 수 있습니다.
  • -
  • 모든 이벤트 객체는 W3C 사양을 준수하고, 모든 이벤트(submit을 포함해)는 W3C 사양에 따라 일으킵(bubble)니다. 좀 더 자세한 정보는 이벤트 시스템을 보세요.
  • -
  • onChange 이벤트는 기대대로 동작합니다. 이 이벤트는 일관성없이 blur시점에서 발생하지 않고 폼 필드가 변경될 때만 발생합니다.1 우리는 의도적으로 기존 브라우저 동작을 차단했습니다. onChange는 이름과 실제 동작이 다르고, React는 실시간으로 사용자 입력에 반응할 때 이 이벤트에 의존하기 때문입니다. 더 자세한 정보는 을 보세요.
  • -
  • valuechecked 폼 input 어트리뷰트, textarea. 자세히 보기.
  • -
- -
-
-
    - -
  1. -

    역주: 일관성 없다는 표현에 대해 부연 설명하자면, 네이티브의 onChange는 변경뿐만 아니라 blur에서도 반응합니다. 

    -
  2. - -
-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/dom-differences-zh-CN.html b/docs/dom-differences-zh-CN.html deleted file mode 100644 index c615b86fae..0000000000 --- a/docs/dom-differences-zh-CN.html +++ /dev/null @@ -1,508 +0,0 @@ - - - - - - - DOM 的不同之处 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- DOM 的不同之处 -

-
- -

React 实现了一个浏览器无关的 事件和DOM 系统,原因是为了性能和跨浏览器的兼容性.我们利用这个机会来清理了一些浏览器DOM实现的一些粗糙边缘.

- -
    -
  • 所有的 DOM properties 和 attributes (包括事件处理器) 都应该 camelCased 来保持和标准的 JavaScript 风格一致.我们在这里故意打破了这个规范是因为规范是不一致的. 然而,data-*aria-* attributes conform to the specs 应该只 lower-cased.
  • -
  • style attribute 接受 camelCased properties 的JavaScript对象 而不是一个CSS字符串. 这保持了和 DOM style JavaScript property 的一致,更有效率,而且阻止了XSS安全漏洞.
  • -
  • 因为 classfor 是 JavaScript的保留字,内建DOM nodes的JSX元素 应该分别使用 attribute名classNamehtmlFor ,(比如 <div className="foo" />).自定义元素应该直接使用 classfor (例如. <my-tag class="foo" /> ).
  • -
  • 所有事件对象遵循 W3C 规范,所有事件(包括提交)正确按W3C规范冒泡.详见Event System.
  • -
  • onChange 事件表现的像你期望的那样:不论何时一个表单域改变了这个事件就会激发,而不是模糊的不一致.我们故意打破了已有浏览器的行为,因为 onChange 对于他的行为来说用词不当,并且React依赖于这个事件来实时响应用户的输入.详见Forms.
  • -
  • 表单 输入attributes 类似 valuechecked,就像textarea一样More here.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/dom-differences.html b/docs/dom-differences.html deleted file mode 100644 index e39e9a461c..0000000000 --- a/docs/dom-differences.html +++ /dev/null @@ -1,508 +0,0 @@ - - - - - - - DOM Differences | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- DOM Differences -

-
- -

React has implemented a browser-independent events and DOM system for performance and cross-browser compatibility reasons. We took the opportunity to clean up a few rough edges in browser DOM implementations.

- -
    -
  • All DOM properties and attributes (including event handlers) should be camelCased to be consistent with standard JavaScript style. We intentionally break with the spec here since the spec is inconsistent. However, data-* and aria-* attributes conform to the specs and should be lower-cased only.
  • -
  • The style attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM style JavaScript property, is more efficient, and prevents XSS security holes.
  • -
  • Since class and for are reserved words in JavaScript, the JSX elements for built-in DOM nodes should use the attribute names className and htmlFor respectively, (eg. <div className="foo" /> ). Custom elements should use class and for directly (eg. <my-tag class="foo" /> ).
  • -
  • All event objects conform to the W3C spec, and all events (including submit) bubble correctly per the W3C spec. See Event System for more details.
  • -
  • The onChange event behaves as you would expect it to: whenever a form field is changed this event is fired rather than inconsistently on blur. We intentionally break from existing browser behavior because onChange is a misnomer for its behavior and React relies on this event to react to user input in real time. See Forms for more details.
  • -
  • Form input attributes such as value and checked, as well as textarea. More here.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/dom-elements.html b/docs/dom-elements.html new file mode 100644 index 0000000000..7d27a457df --- /dev/null +++ b/docs/dom-elements.html @@ -0,0 +1,516 @@ + + + + + + + + + DOM Elements - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ DOM Elements +

+
+ +

React implements a browser-independent DOM system for performance and cross-browser compatibility. We took the opportunity to clean up a few rough edges in browser DOM implementations.

+ +

In React, all DOM properties and attributes (including event handlers) should be camelCased. For example, the HTML attribute tabindex corresponds to the attribute tabIndex in React. The exception is aria-* and data-* attributes, which should be lowercased.

+

Differences In Attributes #

+

There are a number of attributes that work differently between React and HTML:

+

checked #

+

The checked attribute is supported by <input> components of type checkbox or radio. You can use it to set whether the component is checked. This is useful for building controlled components. defaultChecked is the uncontrolled equivalent, which sets whether the component is checked when it is first mounted.

+

className #

+

To specify a CSS class, use the className attribute. This applies to all regular DOM and SVG elements like <div>, <a>, and others.

+ +

If you use React with Web Components (which is uncommon), use the class attribute instead.

+

dangerouslySetInnerHTML #

+

dangerouslySetInnerHTML is React's replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it's easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it's dangerous. For example:

+
function createMarkup() {
+  return {__html: 'First &middot; Second'};
+}
+
+function MyComponent() {
+  return <div dangerouslySetInnerHTML={createMarkup()} />;
+}
+

htmlFor #

+

Since for is a reserved word in JavaScript, React elements use htmlFor instead.

+

onChange #

+

The onChange event behaves as you would expect it to: whenever a form field is changed, this event is fired. We intentionally do not use the existing browser behavior because onChange is a misnomer for its behavior and React relies on this event to handle user input in real time.

+

selected #

+

The selected attribute is supported by <option> components. You can use it to set whether the component is selected. This is useful for building controlled components.

+

style #

+

The style attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM style JavaScript property, is more efficient, and prevents XSS security holes. For example:

+
const divStyle = {
+  color: 'blue',
+  backgroundImage: 'url(' + imgUrl + ')',
+};
+
+function HelloWorldComponent() {
+  return <div style={divStyle}>Hello World!</div>;
+}
+
+

Note that styles are not autoprefixed. To support older browsers, you need to supply corresponding style properties:

+
const divStyle = {
+  WebkitTransition: 'all', // note the capital 'W' here
+  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
+};
+
+function ComponentWithTransition() {
+  return <div style={divStyle}>This should work cross-browser</div>;
+}
+
+

Style keys are camelCased in order to be consistent with accessing the properties on DOM nodes from JS (e.g. node.style.backgroundImage). Vendor prefixes other than ms should begin with a capital letter. This is why WebkitTransition has an uppercase "W".

+

suppressContentEditableWarning #

+

Normally, there is a warning when an element with children is also marked as contentEditable, because it won't work. This attribute suppresses that warning. Don't use this unless you are building a library like Draft.js that manages contentEditable manually.

+

value #

+

The value attribute is supported by <input> and <textarea> components. You can use it to set the value of the component. This is useful for building controlled components. defaultValue is the uncontrolled equivalent, which sets the value of the component when it is first mounted.

+

All Supported HTML Attributes #

+

React supports all data-* and aria-* attributes as well as these attributes:

+
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
+async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
+charSet checked cite classID className colSpan cols content contentEditable
+contextMenu controls coords crossOrigin data dateTime default defer dir
+disabled download draggable encType form formAction formEncType formMethod
+formNoValidate formTarget frameBorder headers height hidden high href hrefLang
+htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
+lang list loop low manifest marginHeight marginWidth max maxLength media
+mediaGroup method min minLength multiple muted name noValidate nonce open
+optimum pattern placeholder poster preload profile radioGroup readOnly rel
+required reversed role rowSpan rows sandbox scope scoped scrolling seamless
+selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step
+style summary tabIndex target title type useMap value width wmode wrap
+
+

These RDFa attributes are supported (several RDFa attributes overlap with standard HTML attributes and thus are excluded from this list):

+
about datatype inlist prefix property resource typeof vocab
+
+

In addition, the following non-standard attributes are supported:

+ +
    +
  • autoCapitalize autoCorrect for Mobile Safari.
  • +
  • color for <link rel="mask-icon" /> in Safari.
  • +
  • itemProp itemScope itemType itemRef itemID for HTML5 microdata.
  • +
  • security for older versions of Internet Explorer.
  • +
  • unselectable for Internet Explorer.
  • +
  • results autoSave for WebKit/Blink input fields of type search.
  • +
+

All Supported SVG Attributes #

+

React supports these SVG attributes:

+
accentHeight accumulate additive alignmentBaseline allowReorder alphabetic
+amplitude arabicForm ascent attributeName attributeType autoReverse azimuth
+baseFrequency baseProfile baselineShift bbox begin bias by calcMode capHeight
+clip clipPath clipPathUnits clipRule colorInterpolation
+colorInterpolationFilters colorProfile colorRendering contentScriptType
+contentStyleType cursor cx cy d decelerate descent diffuseConstant direction
+display divisor dominantBaseline dur dx dy edgeMode elevation enableBackground
+end exponent externalResourcesRequired fill fillOpacity fillRule filter
+filterRes filterUnits floodColor floodOpacity focusable fontFamily fontSize
+fontSizeAdjust fontStretch fontStyle fontVariant fontWeight format from fx fy
+g1 g2 glyphName glyphOrientationHorizontal glyphOrientationVertical glyphRef
+gradientTransform gradientUnits hanging horizAdvX horizOriginX ideographic
+imageRendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength
+kerning keyPoints keySplines keyTimes lengthAdjust letterSpacing lightingColor
+limitingConeAngle local markerEnd markerHeight markerMid markerStart
+markerUnits markerWidth mask maskContentUnits maskUnits mathematical mode
+numOctaves offset opacity operator order orient orientation origin overflow
+overlinePosition overlineThickness paintOrder panose1 pathLength
+patternContentUnits patternTransform patternUnits pointerEvents points
+pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits
+r radius refX refY renderingIntent repeatCount repeatDur requiredExtensions
+requiredFeatures restart result rotate rx ry scale seed shapeRendering slope
+spacing specularConstant specularExponent speed spreadMethod startOffset
+stdDeviation stemh stemv stitchTiles stopColor stopOpacity
+strikethroughPosition strikethroughThickness string stroke strokeDasharray
+strokeDashoffset strokeLinecap strokeLinejoin strokeMiterlimit strokeOpacity
+strokeWidth surfaceScale systemLanguage tableValues targetX targetY textAnchor
+textDecoration textLength textRendering to transform u1 u2 underlinePosition
+underlineThickness unicode unicodeBidi unicodeRange unitsPerEm vAlphabetic
+vHanging vIdeographic vMathematical values vectorEffect version vertAdvY
+vertOriginX vertOriginY viewBox viewTarget visibility widths wordSpacing
+writingMode x x1 x2 xChannelSelector xHeight xlinkActuate xlinkArcrole
+xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace
+y y1 y2 yChannelSelector z zoomAndPan
+
+ +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/environments.html b/docs/environments.html index 7ab6425ec4..c6adb0fde8 100644 --- a/docs/environments.html +++ b/docs/environments.html @@ -1,561 +1,10 @@ - - - - - - Server-side Environments | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Server-side Environments -

-
- -

One of the great things about React is that it doesn't require the DOM as a dependency, which means it is possible to render a React application on the server and send the HTML markup down to the client. There are a few things that React expects, so this guide will help you get started in your preferred environment.

-

Node.js #

-

Node.js is a popular JavaScript runtime that comes with an extensive core library and support for installing packages from npm to expand on the basic functionality. As we've described elsewhere in the documentation, you can install react and react-dom from npm.

- -

Example:

-
var React = require('react');
-var ReactDOMServer = require('react-dom/server');
-
-var element = React.createElement('div', null, 'Hello World!');
-console.log(ReactDOMServer.renderToString(element));
-
-

If you use JSX, you may want to pre-compile your components. Alternatively you may want to consider using Babel's require hook or babel-node.

- -
-

Note:

- -

Some versions of Node.js have an Object.assign implementation that does not preserve key order. This can cause errors when validating the markup, creating a warning that says "React attempted to reuse markup in a container but the checksum was invalid". If you run into this issue, you can override Object.assign to use a polyfill that preserves key order. For more details, see Issue #6451.

-
-

C# #

-

Support for server-side component rendering and JSX compilation (via Babel) in a .NET Framework / ASP.NET environment is provided through our ReactJS.NET project.

-

Nashorn #

-

Nashorn is a lightweight high-performance JavaScript runtime that runs within the JVM. React should run out of the box in Java 8+.

- -

Example:

-
import java.io.IOException;
-import java.io.InputStream;
-import java.io.FileReader;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-
-public class ReactRender
-{
-  public static void main(String[] args) throws ScriptException, IOException {
-    ScriptEngine nashorn = new ScriptEngineManager().getEngineByName("nashorn");
-
-    // These files can be downloaded as a part of the starter kit
-    // from https://facebook.github.io/react
-    nashorn.eval(new FileReader("path/to/react.js"));
-    nashorn.eval(new FileReader("path/to/react-dom-server.js"));
-
-    System.out.println(nashorn.eval(
-      "ReactDOMServer.renderToString(" +
-        "React.createElement('div', null, 'Hello World!')" +
-      ");"
-    ));
-  }
-}
-
-

If your application uses npm packages, or you want to transform JSX in Nashorn, you will need to do some additional environment setup. The following resources may be helpful in getting you started:

- - - -
-

Note:

- -

Using Babel within Nashorn will require Java 8u72+, as update 72 fixed JDK-8135190.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/error-decoder.html b/docs/error-decoder.html index ffd9b72a65..7414fef4a2 100644 --- a/docs/error-decoder.html +++ b/docs/error-decoder.html @@ -1,12 +1,14 @@ + + - Error Decoder | React - - + Error Decoder - React + + @@ -44,31 +46,55 @@
-
+
+ Edit on GitHub +

+ Error Decoder +

+
+ +

In the minified production build of React, we avoid sending down full error messages in order to reduce the number of bytes sent over the wire.

+ +

We highly recommend using the development build locally when debugging your app since it tracks additional debug info and provides helpful warnings about potential problems in your apps, but if you encounter an exception while using the production build, this page will reassemble the original text of the error.

+ + + +
+ + + + +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,48 +329,57 @@
+ - -
- Edit on GitHub -

- Error Decoder -

-
- -

In the minified production build of React, we avoid sending down full error messages in order to reduce the number of bytes sent over the wire.

- -

We highly recommend using the development build locally when debugging your app since it tracks additional debug info and provides helpful warnings about potential problems in your apps, but if you encounter an exception while using the production build, this page will reassemble the original text of the error.

- - - -
- - - - -
- - -
-
- - -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Sistema di Eventi -

-
- -

SyntheticEvent #

-

Ai tuoi gestori di eventi saranno passate istanze di SyntheticEvent, un involucro cross-browser attorno all'evento nativo del browser. Possiede la stessa interfaccia dell'evento nativo del browser, incluso stopPropagation() e preventDefault(), con l'eccezione che gli eventi funzionano in modo identico su tutti i browser.

- -

Se ti trovi nella situazione di avere bisogno dell'evento sottostante del browser per qualunque ragione, usa semplicemente l'attributo nativeEvent per ottenerlo. Ogni oggetto SyntheticEvent ha i seguenti attributi:

-
boolean bubbles
-boolean cancelable
-DOMEventTarget currentTarget
-boolean defaultPrevented
-number eventPhase
-boolean isTrusted
-DOMEvent nativeEvent
-void preventDefault()
-boolean isDefaultPrevented()
-void stopPropagation()
-boolean isPropagationStopped()
-DOMEventTarget target
-number timeStamp
-string type
-
-
-

Nota:

- -

A partire dalla v0.14, restituire false da un gestore di eventi non fermerà più la propagazione dell'evento. Invece, e.stopPropagation() o e.preventDefault() devono essere invocati manualmente, in maniera appropriata.

-
-

Riutilizzo degli eventi #

-

Gli oggetti SyntheticEvent sono gestiti come un pool. Ciò significa che ciascun oggetto SyntheticEvent sarà riutilizzato e tutte le sue proprietà annullate dopo che la callback dell'evento è stata invocata. -Ciò avviene per ragioni di performance. -Per questo motivo non potrai accedere all'evento in maniera asincrona.

-
function onClick(event) {
-  console.log(event); // => oggetto annullato.
-  console.log(event.type); // => "click"
-  var eventType = event.type; // => "click"
-
-  setTimeout(function() {
-    console.log(event.type); // => null
-    console.log(eventType); // => "click"
-  }, 0);
-
-  this.setState({clickEvent: event}); // Non funzionerà. this.state.clickEvent conterrà soltanto valori null.
-  this.setState({eventType: event.type}); // Puoi sempre esportare le singole proprietà dell'evento.
-}
-
-
-

Nota:

- -

Se vuoi accedere alle proprietà dell'evento in maniera asincrona, devi invocare event.persist() sull'evento, che rimuoverà l'evento sintetico dal pool e permetterà ai riferimenti all'evento di essere mantenuti nel codice dell'utente.

-
-

Eventi Supportati #

-

React normalizza gli eventi in modo che abbiano proprietà consistenti su browser differenti.

- -

I gestori di eventi seguenti sono scatenati da un evento nella fase di propagazione. Per registrare un gestore di eventi per la fase di cattura, aggiungi il suffisso Capture al nome dell'evento; ad esempio, anziché usare onClick, useresti onClickCapture per gestire l'evento click nella fase di cattura.

-

Eventi della Clipboard #

-

Nomi degli eventi:

-
onCopy onCut onPaste
-
-

Proprietà:

-
DOMDataTransfer clipboardData
-

Eventi di Composizione #

-

Nomi degli eventi:

-
onCompositionEnd onCompositionStart onCompositionUpdate
-
-

Proprietà:

-
string data
-

Eventi di Tastiera #

-

Nomi degli eventi:

-
onKeyDown onKeyPress onKeyUp
-
-

Proprietà:

-
boolean altKey
-number charCode
-boolean ctrlKey
-boolean getModifierState(key)
-string key
-number keyCode
-string locale
-number location
-boolean metaKey
-boolean repeat
-boolean shiftKey
-number which
-

Eventi del Focus #

-

Nomi degli eventi:

-
onFocus onBlur
-
-

Proprietà:

-
DOMEventTarget relatedTarget
-

Eventi dei Moduli #

-

Nomi degli eventi:

-
onChange onInput onSubmit
-
-

Per maggiori informazioni sull'evento onChange, leggi Moduli.

-

Eventi del Mouse #

-

Nomi degli eventi:

-
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
-onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
-onMouseMove onMouseOut onMouseOver onMouseUp
-
-

Gli eventi onMouseEnter e onMouseLeave vengono propagati dal componente che viene abbandonato a quello in cui viene effettuato l'ingresso anziché seguire la propagazione ordinaria, e non posseggono una fase di cattura.

- -

Proprietà:

-
boolean altKey
-number button
-number buttons
-number clientX
-number clientY
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-number pageX
-number pageY
-DOMEventTarget relatedTarget
-number screenX
-number screenY
-boolean shiftKey
-

Eventi di Selezione #

-

Nomi degli eventi:

-
onSelect
-

Eventi del Tocco #

-

Nomi degli eventi:

-
onTouchCancel onTouchEnd onTouchMove onTouchStart
-
-

Proprietà:

-
boolean altKey
-DOMTouchList changedTouches
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-boolean shiftKey
-DOMTouchList targetTouches
-DOMTouchList touches
-

Eventi UI #

-

Nomi degli eventi:

-
onScroll
-
-

Proprietà:

-
number detail
-DOMAbstractView view
-

Eventi della Rotellina #

-

Nomi degli eventi:

-
onWheel
-
-

Proprietà:

-
number deltaMode
-number deltaX
-number deltaY
-number deltaZ
-

Eventi dei Media #

-

Nomi degli eventi:

-
onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting
-

Eventi delle Immagini #

-

Nomi degli eventi:

-
onLoad onError
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/events-ko-KR.html b/docs/events-ko-KR.html deleted file mode 100644 index 18f63aa3c6..0000000000 --- a/docs/events-ko-KR.html +++ /dev/null @@ -1,652 +0,0 @@ - - - - - - - 이벤트 시스템 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 이벤트 시스템 -

-
- -

통합적인(Synthetic) 이벤트 #

-

이벤트 핸들러는 브라우저의 네이티브 이벤트의 크로스 브라우저 래퍼(wrapper)인SyntheticEvent의 인스턴스에 전달됩니다. 모든 브라우저에서 동작한다는 점을 제외하면, SyntheticEventstopPropagation()preventDefault()를 포함해, 브라우저의 네이티브 이벤트와 같은 인터페이스를 가지고 있습니다.

- -

어떤 이유로 기본 브라우저 이벤트가 필요하다면, 그냥 nativeEvent를 사용해 할 수 있습니다. 모든 SyntheticEvent 객체는 이런 어트리뷰트를 가집니다.

-
boolean bubbles
-boolean cancelable
-DOMEventTarget currentTarget
-boolean defaultPrevented
-number eventPhase
-boolean isTrusted
-DOMEvent nativeEvent
-void preventDefault()
-boolean isDefaultPrevented()
-void stopPropagation()
-boolean isPropagationStopped()
-DOMEventTarget target
-number timeStamp
-string type
-
-
-

주의:

- -

v0.14 시점에서, 이벤트 핸들러에서 false 를 리턴하는 것은 더 이상 이벤트의 전달(propagation)을 멈추지 않습니다. 대신, e.stopPropagation()e.preventDefault()로 적절히 수동으로 트리거해야 합니다.

-
-

이벤트 풀링 #

-

SyntheticEvent는 풀링됩니다. 이는 SyntheticEvent 객체가 재사용될 것이며 이벤트 콜백이 호출된 후 모든 프로퍼티가 null 값을 갖게 된다는 것을 뜻합니다. -이는 성능을 위한 동작입니다. -이 때문에, 비동기 방식으로는 이벤트에 접근할 수 없습니다.

-
function onClick(event) {
-  console.log(event); // => null이 된 객체.
-  console.log(event.type); // => "click"
-  var eventType = event.type; // => "click"
-
-  setTimeout(function() {
-    console.log(event.type); // => null
-    console.log(eventType); // => "click"
-  }, 0);
-
-  this.setState({clickEvent: event}); // 작동하지 않습니다. this.state.clickEvent 는 null값들만을 갖고 있습니다.
-  this.setState({eventType: event.type}); // 여전히 이벤트 프로퍼티를 내보낼 수 있습니다.
-}
-
-
-

주의:

- -

만약 비동기 방식으로 이벤트 프로퍼티에 접근하길 원한다면, 이벤트의 event.persist()를 호출해야 합니다, 이는 풀로부터 통합적인 이벤트를 제거하고 이벤트에 대한 참조는 사용자의 코드에 의해 유지 될 수 있도록 합니다.

-
-

지원되는 이벤트 #

-

React는 다른 브라우저에서 일관된 특성을 가지도록 이벤트를 일반화합니다.

- -

밑에 있는 이벤트 핸들러들은 일으키는(bubbling) 단계에서 이벤트를 트리거합니다. 이벤트 핸들러를 캡처 단계로 등록하려면, 이벤트 이름에 Capture를 붙이면 됩니다. 예를 들어, 캡처 단계의 클릭 이벤트를 다루려면 onClick를 사용하는 대신에 onClickCapture를 사용해야 합니다.

-

클립보드 이벤트 #

-

이벤트 이름:

-
onCopy onCut onPaste
-
-

프로퍼티:

-
DOMDataTransfer clipboardData
-

Composition Events #

-

이벤트 이름:

-
onCompositionEnd onCompositionStart onCompositionUpdate
-
-

프로퍼티:

-
string data
-

키보드 이벤트 #

-

이벤트 이름:

-
onKeyDown onKeyPress onKeyUp
-
-

프로퍼티:

-
boolean altKey
-number charCode
-boolean ctrlKey
-boolean getModifierState(key)
-string key
-number keyCode
-string locale
-number location
-boolean metaKey
-boolean repeat
-boolean shiftKey
-number which
-

포커스 이벤트 #

-

이벤트 이름:

-
onFocus onBlur
-
-

프로퍼티:

-
DOMEventTarget relatedTarget
-
-

이 포커스 이벤트는 폼 엘리먼트뿐만 아니라 모든 React DOM 엘리먼트에서 작동합니다.

-

폼 이벤트 #

-

이벤트 이름:

-
onChange onInput onSubmit
-
-

onChange 이벤트에 대한 더 자세한 정보는 에서 확인하세요.

-

마우스 이벤트 #

-

이벤트 이름:

-
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
-onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
-onMouseMove onMouseOut onMouseOver onMouseUp
-
-

onMouseEnteronMouseLeave 이벤트는 평범하게 일어나는(bubbling) 대신 입력된 엘리먼트에 남겨지도록 엘리먼트에서 전달되고 캡쳐 단계가 없습니다.

- -

프로퍼티:

-
boolean altKey
-number button
-number buttons
-number clientX
-number clientY
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-number pageX
-number pageY
-DOMEventTarget relatedTarget
-number screenX
-number screenY
-boolean shiftKey
-

셀렉션 이벤트 #

-

이벤트 이름:

-
onSelect
-

터치 이벤트 #

-

이벤트 이름:

-
onTouchCancel onTouchEnd onTouchMove onTouchStart
-
-

프로퍼티:

-
boolean altKey
-DOMTouchList changedTouches
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-boolean shiftKey
-DOMTouchList targetTouches
-DOMTouchList touches
-

UI 이벤트 #

-

이벤트 이름:

-
onScroll
-
-

프로퍼티:

-
number detail
-DOMAbstractView view
-

휠 이벤트 #

-

이벤트 이름:

-
onWheel
-
-

프로퍼티:

-
number deltaMode
-number deltaX
-number deltaY
-number deltaZ
-

미디어 이벤트 #

-

이벤트 이름:

-
onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting
-

이미지 이벤트 #

-

이벤트 이름:

-
onLoad onError
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/events-zh-CN.html b/docs/events-zh-CN.html deleted file mode 100644 index b047fc9bfb..0000000000 --- a/docs/events-zh-CN.html +++ /dev/null @@ -1,668 +0,0 @@ - - - - - - - 事件系统 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 事件系统 -

-
- -

合成事件 #

-

事件处理程序通过 合成事件SyntheticEvent)的实例传递,SyntheticEvent 是浏览器原生事件跨浏览器的封装。SyntheticEvent 和浏览器原生事件一样有 stopPropagation()preventDefault() 接口,而且这些接口夸浏览器兼容。

- -

如果出于某些原因想使用浏览器原生事件,可以使用 nativeEvent 属性获取。每个和成事件(SyntheticEvent)对象都有以下属性:

-
boolean bubbles
-boolean cancelable
-DOMEventTarget currentTarget
-boolean defaultPrevented
-number eventPhase
-boolean isTrusted
-DOMEvent nativeEvent
-void preventDefault()
-boolean isDefaultPrevented()
-void stopPropagation()
-boolean isPropagationStopped()
-DOMEventTarget target
-number timeStamp
-string type
-
-
-

注意:

- -

React v0.14 中,事件处理程序返回 false 不再停止事件传播,取而代之,应该根据需要手动触发 e.stopPropagation()e.preventDefault()

-
-

事件池 #

-

SyntheticEvent 是池化的. 这意味着 SyntheticEvent 对象将会被重用并且所有的属性都会在事件回调被调用后被 nullified. -这是因为性能的原因. -因此,你不能异步的访问事件.

-
function onClick(event) {
-  console.log(event); // => nullified object.
-  console.log(event.type); // => "click"
-  var eventType = event.type; // => "click"
-
-  setTimeout(function() {
-    console.log(event.type); // => null
-    console.log(eventType); // => "click"
-  }, 0);
-
-  this.setState({clickEvent: event}); // Won't work. this.state.clickEvent will only contain null values.
-  this.setState({eventType: event.type}); // You can still export event properties.
-}
-
-
-

注意:

- -

如果你想异步访问事件属性,你应该在事件上调用 event.persist() ,这会从池中移除合成事件并允许对事件的引用被用会保留.

-
-

支持的事件 #

-

React 将事件统一化,使事件在不同浏览器上有一致的属性.

- -

下面的事件处理程序在事件冒泡阶段被触发。如果要注册事件捕获处理程序,应该使用 Capture 事件,例如使用 onClickCapture 处理点击事件的捕获阶段,而不是 onClick

-

剪贴板事件 #

-

事件名称:

-
onCopy onCut onPaste
-
-

属性:

-
DOMDataTransfer clipboardData
-

Composition 事件 #

-

事件名称:

-
onCompositionEnd onCompositionStart onCompositionUpdate
-
-

属性:

-
string data
-

键盘事件 #

-

事件名称:

-
onKeyDown onKeyPress onKeyUp
-
-

属性:

-
boolean altKey
-number charCode
-boolean ctrlKey
-boolean getModifierState(key)
-string key
-number keyCode
-string locale
-number location
-boolean metaKey
-boolean repeat
-boolean shiftKey
-number which
-

焦点事件 #

-

事件名称

-
onFocus onBlur
-
-

属性:

-
DOMEventTarget relatedTarget
-
-

焦点事件在所有的React DOM上工作,不仅仅是表单元素.

-

表单事件 #

-

事件名称:

-
onChange onInput onSubmit
-
-

关于 onChange 事件的更多信息,参见 表单组件

-

鼠标事件 #

-

事件名称:

-
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
-onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
-onMouseMove onMouseOut onMouseOver onMouseUp
-
-

onMouseEnteronMouseLeave 事件从离开的元素传播到进入的元素,代替冒泡排序并且没有捕获阶段.

- -

属性:

-
boolean altKey
-number button
-number buttons
-number clientX
-number clientY
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-number pageX
-number pageY
-DOMEventTarget relatedTarget
-number screenX
-number screenY
-boolean shiftKey
-

Selection Events #

-

事件名称:

-
onSelect
-

触控事件 #

-

事件名称:

-
onTouchCancel onTouchEnd onTouchMove onTouchStart
-
-

属性:

-
boolean altKey
-DOMTouchList changedTouches
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-boolean shiftKey
-DOMTouchList targetTouches
-DOMTouchList touches
-

用户界面事件 #

-

事件名称:

-
onScroll
-
-

属性:

-
number detail
-DOMAbstractView view
-

滚轮事件 #

-

事件名称:

-
onWheel
-
-

属性:

-
number deltaMode
-number deltaX
-number deltaY
-number deltaZ
-

媒体事件 #

-

事件名称:

-
onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting
-

图片事件 #

-

事件名称:

-
onLoad onError
-

动画事件 #

-

事件名称:

-
onAnimationStart onAnimationEnd onAnimationIteration
-
-

属性:

-
string animationName
-string pseudoElement
-float elapsedTime
-

Transition Events #

-

事件名称:

-
onTransitionEnd
-
-

属性:

-
string propertyName
-string pseudoElement
-float elapsedTime
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/events.html b/docs/events.html index 83f074a292..c41cd95125 100644 --- a/docs/events.html +++ b/docs/events.html @@ -1,12 +1,14 @@ + + - Event System | React - - + SyntheticEvent - React + + @@ -44,31 +46,268 @@
-
+
+ Edit on GitHub +

+ SyntheticEvent +

+
+ +

This reference guide documents the SyntheticEvent wrapper that forms part of React's Event System. See the Handling Events guide to learn more.

+

Overview #

+

Your event handlers will be passed instances of SyntheticEvent, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers.

+ +

If you find that you need the underlying browser event for some reason, simply use the nativeEvent attribute to get it. Every SyntheticEvent object has the following attributes:

+
boolean bubbles
+boolean cancelable
+DOMEventTarget currentTarget
+boolean defaultPrevented
+number eventPhase
+boolean isTrusted
+DOMEvent nativeEvent
+void preventDefault()
+boolean isDefaultPrevented()
+void stopPropagation()
+boolean isPropagationStopped()
+DOMEventTarget target
+number timeStamp
+string type
+
+
+

Note:

+ +

As of v0.14, returning false from an event handler will no longer stop event propagation. Instead, e.stopPropagation() or e.preventDefault() should be triggered manually, as appropriate.

+
+

Event pooling #

+

The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. +This is for performance reasons. +As such, you cannot access the event in an asynchronous way.

+
function onClick(event) {
+  console.log(event); // => nullified object.
+  console.log(event.type); // => "click"
+  var eventType = event.type; // => "click"
+
+  setTimeout(function() {
+    console.log(event.type); // => null
+    console.log(eventType); // => "click"
+  }, 0);
+
+  // Won't work. this.state.clickEvent will only contain null values.
+  this.setState({clickEvent: event});
+
+  // You can still export event properties.
+  this.setState({eventType: event.type});
+}
+
+
+

Note:

+ +

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

+
+

Supported Events #

+

React normalizes events so that they have consistent properties across different browsers.

+ +

The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.

+ + + +
+

Reference #

Clipboard Events #

+

Event names:

+
onCopy onCut onPaste
+
+

Properties:

+
DOMDataTransfer clipboardData
+
+
+

Composition Events #

+

Event names:

+
onCompositionEnd onCompositionStart onCompositionUpdate
+
+

Properties:

+
string data
+
+
+

Keyboard Events #

+

Event names:

+
onKeyDown onKeyPress onKeyUp
+
+

Properties:

+
boolean altKey
+number charCode
+boolean ctrlKey
+boolean getModifierState(key)
+string key
+number keyCode
+string locale
+number location
+boolean metaKey
+boolean repeat
+boolean shiftKey
+number which
+
+
+

Focus Events #

+

Event names:

+
onFocus onBlur
+
+

These focus events work on all elements in the React DOM, not just form elements.

+ +

Properties:

+
DOMEventTarget relatedTarget
+
+
+

Form Events #

+

Event names:

+
onChange onInput onSubmit
+
+

For more information about the onChange event, see Forms.

+ +
+

Mouse Events #

+

Event names:

+
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
+onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
+onMouseMove onMouseOut onMouseOver onMouseUp
+
+

The onMouseEnter and onMouseLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.

+ +

Properties:

+
boolean altKey
+number button
+number buttons
+number clientX
+number clientY
+boolean ctrlKey
+boolean getModifierState(key)
+boolean metaKey
+number pageX
+number pageY
+DOMEventTarget relatedTarget
+number screenX
+number screenY
+boolean shiftKey
+
+
+

Selection Events #

+

Event names:

+
onSelect
+
+
+

Touch Events #

+

Event names:

+
onTouchCancel onTouchEnd onTouchMove onTouchStart
+
+

Properties:

+
boolean altKey
+DOMTouchList changedTouches
+boolean ctrlKey
+boolean getModifierState(key)
+boolean metaKey
+boolean shiftKey
+DOMTouchList targetTouches
+DOMTouchList touches
+
+
+

UI Events #

+

Event names:

+
onScroll
+
+

Properties:

+
number detail
+DOMAbstractView view
+
+
+

Wheel Events #

+

Event names:

+
onWheel
+
+

Properties:

+
number deltaMode
+number deltaX
+number deltaY
+number deltaZ
+
+
+

Media Events #

+

Event names:

+
onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted 
+onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay 
+onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend 
+onTimeUpdate onVolumeChange onWaiting
+
+
+

Image Events #

+

Event names:

+
onLoad onError
+
+
+

Animation Events #

+

Event names:

+
onAnimationStart onAnimationEnd onAnimationIteration
+
+

Properties:

+
string animationName
+string pseudoElement
+float elapsedTime
+
+
+

Transition Events #

+

Event names:

+
onTransitionEnd
+
+

Properties:

+
string propertyName
+string pseudoElement
+float elapsedTime
+
+ +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,219 +542,57 @@
+ - -
- Edit on GitHub -

- Event System -

-
- -

SyntheticEvent #

-

Your event handlers will be passed instances of SyntheticEvent, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers.

- -

If you find that you need the underlying browser event for some reason, simply use the nativeEvent attribute to get it. Every SyntheticEvent object has the following attributes:

-
boolean bubbles
-boolean cancelable
-DOMEventTarget currentTarget
-boolean defaultPrevented
-number eventPhase
-boolean isTrusted
-DOMEvent nativeEvent
-void preventDefault()
-boolean isDefaultPrevented()
-void stopPropagation()
-boolean isPropagationStopped()
-DOMEventTarget target
-number timeStamp
-string type
-
-
-

Note:

- -

As of v0.14, returning false from an event handler will no longer stop event propagation. Instead, e.stopPropagation() or e.preventDefault() should be triggered manually, as appropriate.

-
-

Event pooling #

-

The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. -This is for performance reasons. -As such, you cannot access the event in an asynchronous way.

-
function onClick(event) {
-  console.log(event); // => nullified object.
-  console.log(event.type); // => "click"
-  var eventType = event.type; // => "click"
-
-  setTimeout(function() {
-    console.log(event.type); // => null
-    console.log(eventType); // => "click"
-  }, 0);
-
-  // Won't work. this.state.clickEvent will only contain null values.
-  this.setState({clickEvent: event});
-
-  // You can still export event properties.
-  this.setState({eventType: event.type});
-}
-
-
-

Note:

- -

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

-
-

Supported Events #

-

React normalizes events so that they have consistent properties across different browsers.

- -

The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.

-

Clipboard Events #

-

Event names:

-
onCopy onCut onPaste
-
-

Properties:

-
DOMDataTransfer clipboardData
-

Composition Events #

-

Event names:

-
onCompositionEnd onCompositionStart onCompositionUpdate
-
-

Properties:

-
string data
-

Keyboard Events #

-

Event names:

-
onKeyDown onKeyPress onKeyUp
-
-

Properties:

-
boolean altKey
-number charCode
-boolean ctrlKey
-boolean getModifierState(key)
-string key
-number keyCode
-string locale
-number location
-boolean metaKey
-boolean repeat
-boolean shiftKey
-number which
-

Focus Events #

-

Event names:

-
onFocus onBlur
-
-

Properties:

-
DOMEventTarget relatedTarget
-
-

These focus events work on all elements in the React DOM, not just form elements.

-

Form Events #

-

Event names:

-
onChange onInput onSubmit
-
-

For more information about the onChange event, see Forms.

-

Mouse Events #

-

Event names:

-
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
-onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
-onMouseMove onMouseOut onMouseOver onMouseUp
-
-

The onMouseEnter and onMouseLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.

- -

Properties:

-
boolean altKey
-number button
-number buttons
-number clientX
-number clientY
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-number pageX
-number pageY
-DOMEventTarget relatedTarget
-number screenX
-number screenY
-boolean shiftKey
-

Selection Events #

-

Event names:

-
onSelect
-

Touch Events #

-

Event names:

-
onTouchCancel onTouchEnd onTouchMove onTouchStart
-
-

Properties:

-
boolean altKey
-DOMTouchList changedTouches
-boolean ctrlKey
-boolean getModifierState(key)
-boolean metaKey
-boolean shiftKey
-DOMTouchList targetTouches
-DOMTouchList touches
-

UI Events #

-

Event names:

-
onScroll
-
-

Properties:

-
number detail
-DOMAbstractView view
-

Wheel Events #

-

Event names:

-
onWheel
-
-

Properties:

-
number deltaMode
-number deltaX
-number deltaY
-number deltaZ
-

Media Events #

-

Event names:

-
onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted 
-onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay 
-onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend 
-onTimeUpdate onVolumeChange onWaiting
-

Image Events #

-

Event names:

-
onLoad onError
-

Animation Events #

-

Event names:

-
onAnimationStart onAnimationEnd onAnimationIteration
-
-

Properties:

-
string animationName
-string pseudoElement
-float elapsedTime
-

Transition Events #

-

Event names:

-
onTransitionEnd
-
-

Properties:

-
string propertyName
-string pseudoElement
-float elapsedTime
-
- -
- - ← Prev - - - Next → - -
-
- - -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Architettura di un'Applicazione Flux -

-
- -

Questa pagina è stata spostata sul sito di Flux. Leggila qui.

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/flux-overview-ko-KR.html b/docs/flux-overview-ko-KR.html deleted file mode 100644 index fdcfc6dfef..0000000000 --- a/docs/flux-overview-ko-KR.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Flux 애플리케이션 아키텍쳐 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Flux 애플리케이션 아키텍쳐 -

-
- -

이 페이지는 Flux 웹사이트로 이동되었습니다. 거기서 보세요.

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/flux-overview-zh-CN.html b/docs/flux-overview-zh-CN.html deleted file mode 100644 index c264fa95af..0000000000 --- a/docs/flux-overview-zh-CN.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Flux 应用架构 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Flux 应用架构 -

-
- -

本页被移到了 Flux 网站。点击访问

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/flux-overview.html b/docs/flux-overview.html deleted file mode 100644 index a9b8a545d8..0000000000 --- a/docs/flux-overview.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Flux Application Architecture | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Flux Application Architecture -

-
- -

This page has been moved to the Flux website. View it there.

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/flux-todo-list-it-IT.html b/docs/flux-todo-list-it-IT.html deleted file mode 100644 index 660f93bc34..0000000000 --- a/docs/flux-todo-list-it-IT.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Tutorial TodoMVC Flux | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Tutorial TodoMVC Flux -

-
- -

Questa pagina è stata spostata sul sito di Flux. Leggila qui.

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/flux-todo-list-ko-KR.html b/docs/flux-todo-list-ko-KR.html deleted file mode 100644 index acc3dec4c1..0000000000 --- a/docs/flux-todo-list-ko-KR.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Flux TodoMVC 튜토리얼 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Flux TodoMVC 튜토리얼 -

-
- -

이 페이지는 Flux 웹사이트로 이동되었습니다. 거기서 보세요.

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/flux-todo-list-zh-CN.html b/docs/flux-todo-list-zh-CN.html deleted file mode 100644 index 8d635c8aff..0000000000 --- a/docs/flux-todo-list-zh-CN.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Flux TodoMVC 教程 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Flux TodoMVC 教程 -

-
- -

本页被移到了 Flux 网站。点击访问

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/flux-todo-list.html b/docs/flux-todo-list.html deleted file mode 100644 index 74403dfa17..0000000000 --- a/docs/flux-todo-list.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Flux TodoMVC Tutorial | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Flux TodoMVC Tutorial -

-
- -

This page has been moved to the Flux website. View it there.

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/forms-it-IT.html b/docs/forms-it-IT.html deleted file mode 100644 index bb29e28aab..0000000000 --- a/docs/forms-it-IT.html +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - - Moduli | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Moduli -

-
- -

I componenti dei moduli come <input>, <textarea> e <option> differiscono dagli altri componenti nativi poiché possono essere alterati tramite interazione dell'utente. Questi componenti forniscono interfacce che rendono più semplice gestire i moduli in risposta all'interazione dell'utente.

- -

Per maggiori informazioni sugli eventi dell'elemento <form> consulta Eventi dei Moduli.

-

Proprietà Interattive #

-

I componenti dei moduli supportano un numero di proprietà che vengono modificate dall'interazione dell'utente:

- -
    -
  • value, supportato dai elementi <input> e <textarea>.
  • -
  • checked, supportato dagli elementi <input> dal tipo checkbox o radio.
  • -
  • selected, supportato dagli elementi <option>.
  • -
- -

In HTML, in valore di <textarea> è impostato tramite un nodo di testo figlio. In React, devi invece usare la proprietà value.

- -

I componenti dei moduli ti permettono di reagire ai cambiamenti impostando una callback come proprietà onChange. La proprietà onChange funziona in tutti i browser e viene scatenata in risposta all'interazione dell'utente quando:

- -
    -
  • Il value di <input> o <textarea> cambia.
  • -
  • Lo stato checked di <input> cambia.
  • -
  • Lo stato selected di <option> cambia.
  • -
- -

Come tutti gli eventi DOM, la proprietà onChange è supportata su tutti i componenti nativi e può essere usata per gestire la propagazione di eventi di cambiamento.

- -
-

Nota:

- -

Per <input> e <textarea>, onChange rimpiazza — e dovrebbe generalmente essere utilizzata in sostituzione — il gestore di eventi oninput nativo del DOM.

-
-

Componenti Controllati #

-

Un <input> il cui value è impostato è un componente controllato. In un <input> controllato, il valore dell'elemento visualizzato si riflette sempre nella sua proprietà value. Ad esempio:

-
  render: function() {
-    return <input type="text" value="Ciao!" />;
-  }
-
-

Ciò visualizzerà un input che ha sempre il valore di value impostato a Ciao!. Ciascuna immissione dell'utente non avrà effetto sull'elemento visualizzato poiché React ha dichiarato il suo value pari a Ciao!. Se volessi aggiornare il value in risposta all'input dell'utente, puoi usare l'evento onChange:

-
  getInitialState: function() {
-    return {value: 'Ciao!'};
-  },
-  handleChange: function(event) {
-    this.setState({value: event.target.value});
-  },
-  render: function() {
-    var value = this.state.value;
-    return <input type="text" value={value} onChange={this.handleChange} />;
-  }
-
-

In questo esempio, stiamo semplicemente accettando il valore più recente fornito dall'utente e aggiornando la proprietà value del componente <input>. Questo pattern semplifica l'implementazione di interfacce che rispondono o validano l'interazione dell'utente. Ad esempio:

-
  handleChange: function(event) {
-    this.setState({value: event.target.value.substr(0, 140)});
-  }
-
-

Così si può accettare l'input dell'utente ma ne tronca il valore ai primi 140 caratteri.

-

Potenziali Problemi con Checkbox e Radio Button #

-

Fai attenzione che, allo scopo di normalizzare la gestione del cambiamento degli elementi checkbox e radio button, React usa un evento click al posto di un evento change. Nella maggior parte dei casi questo funziona nel modo previsto, tranne quando viene usato preventDefault in un gestore dell'evento change. preventDefault impedisce al browser di aggiornare visualmente l'input, anche se checked cambia il suo valore. Questo può essere evitato rimuovendo la chiamata a preventDefault, oppure effettuando il cambio del valore di checked tramite setTimeout.

-

Componenti Non Controllati #

-

Un <input> che non fornisce un value (o lo imposta a null) è un componente non controllato. In un <input> non controllato, il valore dell'elemento visualizzato rifletterà l'input dell'utente. Ad esempio:

-
  render: function() {
-    return <input type="text" />;
-  }
-
-

Questo visualizzerà un campo di input il cui valore iniziale è vuoto. Ciascun input dell'utente si rifletterà immediatamente nell'elemento visualizzato. Se desideri reagire ai cambiamenti del valore, puoi usare il gestore di eventi onChange proprio come con i componenti controllati.

-

Valore Predefinito #

-

Se desideri inizializzare il componente con un valore non vuoto, puoi fornire una proprietà defaultValue. Ad esempio:

-
  render: function() {
-    return <input type="text" defaultValue="Ciao!" />;
-  }
-
-

Questo esempio funzionerà in maniera simile all'esempio precedente sui Componenti Controllati.

- -

Similmente, <input> supporta defaultChecked e <select> supporta defaultValue.

- -
-

Nota:

- -

Le proprietà defaultValue e defaultChecked sono usate soltanto durante il rendering iniziale. Se devi aggiornare il valore in un rendering successivo, dovrai usare un componente controllato.

-
-

Argomenti Avanzati #

Perché Componenti Controllati? #

-

Usare componenti di moduli come <input> in React presenta una difficoltà aggiuntiva, assente quando si scrive un modulo tradizionale in HTML. Ad esempio, in HTML:

-
  <input type="text" name="title" value="Senza titolo" />
-
-

Questo visualizza un campo di input inizializzato con il valore Senza titolo. Quando l'utente modifica il campo, la proprietà value del nodo cambierà. Tuttavia, node.getAttribute('value') restituirà ancora il valore usato durante l'inizializzazione, Senza titolo.

- -

Diversamente dall'HTML, i componenti React devono rappresentare lo stato della vista in ciascun momento e non soltanto durante l'inizializzazione. Ad esempio, in React:

-
  render: function() {
-    return <input type="text" name="title" value="Senza titolo" />;
-  }
-
-

Dal momento che questo metodo descrive la vista in ogni momento, il valore del campo di testo deve sempre essere Senza titolo.

-

Perché il Valore della Textarea? #

-

In HTML, il valore di <textarea> è solitamente impostato usando un nodo di testo figlio:

-
  <!-- antipattern: NON FARLO! -->
-  <textarea name="description">Questa è la descrizione.</textarea>
-
-

Per l'HTML, questo approccio permette agli sviluppatori di fornire facilmente valori su più righe. Tuttavia, dal momento che React è JavaScript, non abbiamo limitazioni sulle stringhe e possiamo usare \n se desideriamo andare a capo. In un mondo in cui abbiamo value e defaultValue, il ruolo giocato dal nodo figlio è ambiguo. Per questa ragione, non dovresti utilizzare il nodo figlio quando imposti il valore delle <textarea>:

-
  <textarea name="description" value="Questa è la descrizione." />
-
-

Se tuttavia decidi di usare il nodo di testo figlio, questo si comporterà come defaultValue.

-

Perché il Value di Select? #

-

L'elemento <option> selezionato in un elemento HTML <select> è normalmente specificato attraverso l'attributo selected dell'opzione stessa. In React, allo scopo di rendere i componenti più semplici da manipolare, viene invece adottato il formato seguente:

-
  <select value="B">
-    <option value="A">Arancia</option>
-    <option value="B">Banana</option>
-    <option value="C">Ciliegia</option>
-  </select>
-
-

Per creare un componente non controllato, viene invece usato defaultValue.

- -
-

Nota:

- -

Puoi passare un array come valore dell'attributo value, se desideri selezionare più opzioni in un tag select a scelta multipla: <select multiple={true} value={['B', 'C']}>.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/forms-ja-JP.html b/docs/forms-ja-JP.html deleted file mode 100644 index 8229aec9a2..0000000000 --- a/docs/forms-ja-JP.html +++ /dev/null @@ -1,601 +0,0 @@ - - - - - - - フォーム | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- フォーム -

-
- -

<input><textarea><option> のようなフォームのコンポーネントはユーザの入力によって変化しうるので、他のネイティブのコンポーネントとは異なります。以下のコンポーネントは、ユーザの入力に返答することにおいて、フォームを操作することを簡単にするインターフェースを提供します。

- -

<form> のイベントについての情報は、フォームのイベントをご覧ください。

-

双方向のprops #

-

以下のように、フォームのコンポーネントはユーザの入力に影響されるいくつかのpropsをサポートしています。

- -
    -
  • value<input><textarea> コンポーネントにサポートされています。
  • -
  • checked<input> コンポーネントの checkboxradio タイプにサポートされています。
  • -
  • selected<option> コンポーネントにサポートされています。
  • -
- -

HTMLでは、 <textarea> の値は子要素によってセットされます。Reactでは、 value を代わりに使うべきです。

- -

フォームコンポーネントは onChange propにコールバックをセットすることで変更を検知することを可能にします。onChange propはブラウザ上で、ユーザの入力に返答する際に発火するために動きます。それは以下のようなタイミングです。

- -
    -
  • <input><textarea>value が変わる時。
  • -
  • <input>checked ステータスが変わる時。
  • -
  • <option>selected ステータスが変わる時。
  • -
- -

全てのDOMのイベントのように、 onChange propは全てのネイティブのコンポーネントにサポートされており、何度も発生するチェンジイベントを検知するのに使われることもあります。

- -
-

注意: -<input><textarea> にとって、 onChange は DOMのビルトインの oninput イベントハンドラの代替のものです。そして、一般的に、代わりに使われています。

-
-

制御されたコンポーネント #

-

<input>value のセットは 制御された コンポーネントです。制御された <input> では、レンダリングされた要素の値は、常に value propを反映します。例えば、

-
  render: function() {
-    return <input type="text" value="Hello!" />;
-  }
-
-

上記は、常に Hello! という値を持つinputをレンダリングするでしょう。ユーザのinputはレンダリングされた要素に何も影響を与えないでしょう。なぜなら、Reactが、値が Hello! になるように宣言しているからです。ユーザのinputに返答する形で値を更新したいなら、以下のように onChange イベントが使用できます。

-
  getInitialState: function() {
-    return {value: 'Hello!'};
-  },
-  handleChange: function(event) {
-    this.setState({value: event.target.value});
-  },
-  render: function() {
-    var value = this.state.value;
-    return <input type="text" value={value} onChange={this.handleChange} />;
-  }
-
-

この例では、ユーザから提供された、最新の値を単純に受け入れ <input> コンポーネントの value propを更新します。 このパターンはユーザの入力に返答したり、バリデーションしたりするインターフェースを実行することを簡単にします。例えば、

-
  handleChange: function(event) {
-    this.setState({value: event.target.value.substr(0, 140)});
-  }
-
-

上記はユーザのinputを受け入れますが、値を最初の140字に切り取ります。

-

制御されないコンポーネント #

-

value を与えられていない(もしくは null がセットされている) <input>制御されない コンポーネントです。制御されない <input> では、レンダリングされた要素の値はユーザのinputを反映します。例えば、

-
  render: function() {
-    return <input type="text" />;
-  }
-
-

上記は、空の値で最初は始まるinputをレンダリングします。どのようなユーザのinputも即座にレンダリングされた要素によって反映されます。値の更新を検知したいなら、 onChange イベントを、制御されたコンポーネントと同様に使用することができます。

- -

コンポーネントを空ではない値で初期化したいなら、 defaultValue propを提供することができます。例えば、

-
  render: function() {
-    return <input type="text" defaultValue="Hello!" />;
-  }
-
-

この例は、上記の 制御されたコンポーネント の例と同じように動くでしょう。

- -

同様に、 <input>defaultChecked をサポートし、 <select>defaultValue をサポートします。

-

高度なトピック #

なぜコントロールされたコンポーネントを使うのでしょうか? #

-

<input> のようなフォームのコンポーネントをReactで使うことは、伝統的なHTMLのフォームを書いた時には無視される表現であることを表します。例えば、HTMLでは、

-
  <input type="text" name="title" value="Untitled" />
-
-

上記は、 Untitled という値で 初期化 されたinputをレンダリングします。ユーザがinputを更新する時、ノードの value プロパティ が変更されるでしょう。しかし、 node.getAttribute('value') は初期化の際に使用された値である Untitled をまだリターンします。

- -

HTMLと違って、Reactのコンポーネントは初期化の時だけではなく、いつでもビューのステータスを再度表示しなくてはなりません。例えば、Reactでは、

-
  render: function() {
-    return <input type="text" name="title" value="Untitled" />;
-  }
-
-

このメソッドがいつでもビューを描画するので、次のテキストの入力の値は 常に Untitled になります。

-

なぜテキストエリアの値を使うのでしょうか? #

-

HTMLでは、 <textarea> の値は普通、以下のようにその子要素を使うことでセットされます。

-
  <!-- 反例: このようにはしないでください! -->
-  <textarea name="description">This is the description.</textarea>
-
-

HTMLでは、開発者は簡単に複数行に渡る値を提供できます。しかし、ReactがJavaScriptであるので、文字列の制限を私たちは持っておらず、改行をしたい場合は \n を使えます。 valuedefaultValue を私たちが持っている世界では、子要素が果たす役割は曖昧になっています。この理由から、以下のように <textarea> の値をセットする際には子要素を使うべきではありません。

-
  <textarea name="description" value="This is a description." />
-
-

子要素を使うことを 決めた 場合は、 defaultValue と同様の動きをします。

-

なぜセレクトバリューを使うのでしょうか? #

-

HTMLの <select> の選択された <option> は、普通はオプションの selected 属性によって指定されます。Reactでは、コンポーネントの操作を簡単にするために、以下のようなフォーマットが代わりに適用されます。

-
  <select value="B">
-    <option value="A">Apple</option>
-    <option value="B">Banana</option>
-    <option value="C">Cranberry</option>
-  </select>
-
-

制御されないコンポーネントを作成するために、 defaultValue が代わりに使われます。

- -
-

注意: -配列を value 属性の中に渡すことができます。これで、以下のように、 select タグの中で複数のオプションを選択することができます。 <select multiple={true} value={['B', 'C']}>

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/forms-ko-KR.html b/docs/forms-ko-KR.html deleted file mode 100644 index 3177ca41c7..0000000000 --- a/docs/forms-ko-KR.html +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - - 폼 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 폼 -

-
- -

<input>, <textarea>, <option> 같은 폼 컴포넌트는 다른 네이티브 컴포넌트와 다릅니다. 왜냐하면, 사용자의 상호작용에 의해 변경될 수 있기 때문이죠. 이런 컴포넌트들은 사용자의 상호작용에 반응하여 폼을 더 쉽게 관리할 수 있도록 인터페이스를 제공합니다.

- -

<form> 이벤트에 관한 정보는 폼 이벤트를 보세요.

-

Props의 상호작용 #

-

폼 컴포넌트는 사용자 상호작용을 통해 영향을 받는 몇 가지 props를 지원합니다.

- -
    -
  • value: <input>, <textarea> 컴포넌트에서 사용가능.
  • -
  • checked: checkbox, radio타입의 <input> 컴포넌트에서 사용가능.
  • -
  • selected: <option> 컴포넌트에서 사용가능.
  • -
- -

HTML에서는 <textarea> 태그의 값을 설정할 때 <textarea> 태그의 자식이 사용되지만, React에서는 value 를 사용해야 합니다.

- -

폼 컴포넌트는 onChange prop의 콜백을 설정하여 변경을 감시(listening)할 수 있습니다. onChange prop는 브라우저에 관계없이 다음과 같은 사용자 상호작용에 반응합니다.

- -
    -
  • <input>, <textarea>value 변경.
  • -
  • <input>checked state 변경.
  • -
  • <option>selected state 변경.
  • -
- -

모든 DOM 이벤트처럼 onChange prop은 모든 네이티브 컴포넌트에서 지원되며 일어난(bubbled) 변경 이벤트를 감시하는데 사용할 수 있습니다.

- -
-

주의:

- -

<input>, <textarea>에서는 onChange가 DOM의 oninput 이벤트 핸들러와 같은 기능을 제공하므로 일반적인 경우에는 onChange를 사용하세요.

-
-

제어되는(controlled) 컴포넌트 #

-

value가 설정된 <input>제어되는 컴포넌트입니다. 제어되는 <input>에서, 렌더 엘리먼트의 값은 항상 value prop을 반영합니다. 예를 들어,

-
  render: function() {
-    return <input type="text" value="Hello!" />;
-  }
-
-

이것은 항상 Hello!의 값을 가지는 input을 렌더합니다. 어떤 사용자 입력도 렌더된 엘리먼트에는 영향을 주지 않는데, 왜냐하면 React가 값을 Hello!로 설정했기 때문입니다. 사용자 입력에 따라 값을 업데이트하길 원한다면, onChange 이벤트를 사용할 수 있습니다.

-
  getInitialState: function() {
-    return {value: 'Hello!'};
-  },
-  handleChange: function(event) {
-    this.setState({value: event.target.value});
-  },
-  render: function() {
-    var value = this.state.value;
-    return <input type="text" value={value} onChange={this.handleChange} />;
-  }
-
-

이 예제에서는, 단순히 사용자가 주는 최신값을 받고 <input> 컴포넌트의 value prop을 업데이트하고 있습니다. 이 패턴은 사용자의 상호작용에 반응하거나 검증하는 인터페이스를 쉽게 구현하게 합니다. 예를 들어,

-
  handleChange: function(event) {
-    this.setState({value: event.target.value.substr(0, 140)});
-  }
-
-

이것은 사용자 입력을 받아들이지만, 시작에서부터 140자로 값을 자릅니다.

-

체크박스와 라디오 버튼의 잠재적인 문제 #

-

변경 핸들링을 일반화하기 위해 React는 change 이벤트 대신에 click 이벤트를 사용하는 것에 주의하세요. change 핸들러 안에서 preventDefault를 호출하는 경우를 제외하고 이 동작은 예상대로 동작합니다. 이런 경우 preventDefault를 제거하거나, setTimeoutchecked의 전환을 넣어서 해결 가능합니다.

-

제어되지 않는(Uncontrolled) 컴포넌트 #

-

value 가 없(거나 null로 설정되어 있)는 <input>제어되지 않는 컴포넌트입니다. 제어되지 않는 <input>에서 렌더된 엘리먼트의 value값은 사용자의 입력을 반영합니다. 예를 들어,

-
  render: function() {
-    return <input type="text" />;
-  }
-
-

이것은 빈 값으로 시작되는 input을 렌더합니다. 임의의 사용자 입력은 즉시 렌더된 엘리먼트에 반영됩니다. 값의 업데이트를 감시하길 원한다면, 제어되는 컴포넌트처럼 onChange 이벤트를 사용할 수 있습니다.

-

기본 값 #

-

비어 있지 않은 값으로 초기화하길 원한다면, defaultValue prop로 할 수 있습니다. 예를 들어,

-
  render: function() {
-    return <input type="text" defaultValue="Hello!" />;
-  }
-
-

이 예제는 위에있는 제어되지 않는 컴포넌트에 더 가깝게 동작할 것입니다.

- -

마찬가지로, <input>defaultChecked를 지원하고 <select>defaultValue를 지원합니다.

- -
-

주의:

- -

defaultValue, defaultChecked prop은 최초 렌더에서만 사용됩니다. 뒤에 일어나는 렌더에서 값을 업데이트할 필요가 있다면, 제어되는(controlled) 컴포넌트를 사용하셔야 합니다.

-
-

심화 주제 #

왜 제어되는 컴포넌트인가요? #

-

React에서 <input>같은 폼 컴포넌트를 사용하면, 전통적인 폼 HTML을 쓸 때에는 없던 어려운 문제가 있습니다. 예를 들어 HTML에서

-
  <input type="text" name="title" value="Untitled" />
-
-

이렇게 하면 input은 Untitled 값으로 초기화 됩니다. 사용자가 input을 업데이트할 때, 노드의 value 프로퍼티가 변경될 것입니다. 하지만, node.getAttribute('value')은 여전히 초기화 때 사용했던 값인 Untitled를 리턴합니다.

- -

HTML과 다르게, React 컴포넌트는 초기화 시점 뿐만 아니라, 어떤 시점이라도 반드시 뷰의 state를 나타내야 합니다. 예를 들어 React에서

-
  render: function() {
-    return <input type="text" name="title" value="Untitled" />;
-  }
-
-

이 메소드가 어떤 시점에도 뷰를 기술하기 때문에, 텍스트 input의 값은 언제나 Untitled입니다.

-

왜 Textarea에 value를 사용하나요? #

-

HTML에서, <textarea>의 값은 보통 그것의 자식들로 설정됩니다.

-
  <!-- 안티패턴: 이렇게 하지 마세요! -->
-  <textarea name="description">이것은 설명입니다.</textarea>
-
-

HTML에서는 이렇게 하면 여러 줄의 값을 쉽게 개발자가 넣을 수 있게 합니다. 하지만, React는 JavaScript기 때문에, 우리는 문자열 제한이 없고 개행이 필요하면 \n을 사용할 수 있습니다. 이 곳에서는 valuedefaultValue가 있고, 그것이 자식들의 역할을 모호하게 합니다. 이런 이유로, <textarea>의 값을 설정할 때에는 자식들을 사용하지 않아야 합니다.

-
  <textarea name="description" value="이것은 설명입니다." />
-
-

자식들을 사용하기로 했다면, 자식들은 defaultValue처럼 동작할 것입니다.

-

왜 Select에 value를 사용하나요? #

-

HTML <select>에서 선택된 <option>은 보통 option의 selected 어트리뷰트로 기술됩니다. React에서는 컴포넌트를 관리하기 쉽게 하기 위해, 다음 형식이 대신 채용됐습니다.

-
  <select value="B">
-    <option value="A">Apple</option>
-    <option value="B">Banana</option>
-    <option value="C">Cranberry</option>
-  </select>
-
-

제어되지 않는 컴포넌트로 만드려면, 대신 defaultValue를 사용하세요.

- -
-

주의:

- -

select 태그에 여러 옵션을 선택할 수 있도록, value 어트리뷰트에 배열을 넘길 수도 있습니다. <select multiple={true} value={['B', 'C']}>

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/forms-zh-CN.html b/docs/forms-zh-CN.html deleted file mode 100644 index 1c9cfeb779..0000000000 --- a/docs/forms-zh-CN.html +++ /dev/null @@ -1,620 +0,0 @@ - - - - - - - 表单组件 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 表单组件 -

-
- -

诸如 <input><textarea><option> 这样的表单组件不同于其他原生组件,因为他们可以通过用户交互发生变化。这些组件提供的界面使响应用户交互的表单数据处理更加容易。

- -

关于 <form> 事件详情请查看 表单事件

-

交互属性 #

-

表单组件支持几个受用户交互影响的属性:

- -
    -
  • value,用于 <input><textarea> 组件。
  • -
  • checked,用于类型为 checkbox 或者 radio<input> 组件。
  • -
  • selected,用于 <option> 组件。
  • -
- -

在 HTML 中,<textarea> 的值通过子节点设置;在 React 中则应该使用 value 代替。

- -

表单组件可以通过 onChange 回调函数来监听组件变化。当用户做出以下交互时,onChange 执行并通过浏览器做出响应:

- -
    -
  • <input><textarea>value 发生变化时。
  • -
  • <input>checked 状态改变时。
  • -
  • <option>selected 状态改变时。
  • -
- -

和所有 DOM 事件一样,所有的 HTML 原生组件都支持 onChange 属性,而且可以用来监听冒泡的 change 事件。

- -
-

注意:

- -

对于 <input> and <textarea>onChange 取代 — 一般应该用来替代 — DOM内建的 oninput 事件处理。

-
-

受控组件 #

-

一个受控<input> 有一个 value prop。渲染一个受控 <input> 会反映 value prop 的值。

-
  render: function() {
-    return <input type="text" value="Hello!" />;
-  }
-
-

用户输入在被渲染的元素里将没有作用,因为 React 已经声明值为 Hello!。要更新 value 来响应用户输入,你可以使用 onChange 事件:

-
  getInitialState: function() {
-    return {value: 'Hello!'};
-  },
-  handleChange: function(event) {
-    this.setState({value: event.target.value});
-  },
-  render: function() {
-    return (
-      <input
-        type="text"
-        value={this.state.value}
-        onChange={this.handleChange}
-      />
-    );
-  }
-
-

在这个例子中,我们接受用户提供的值并更新 <input> 组件的 value prop。这个模式使实现响应或者验证用户输入的界面更容易。例如:

-
  handleChange: function(event) {
-    this.setState({value: event.target.value.substr(0, 140)});
-  }
-
-

上面的代码接受用户输入,并截取前 140 个字符。

- -

受控组件不维持一个自己的内部状态;它单纯的基于 props 渲染。

-

复选框与单选按钮的潜在问题 #

-

当心,在力图标准化复选框与单选按钮的变换处理中,React使用 click 事件代替 change 事件。在大多数情况下它们表现的如同预期,除了在change handler中调用preventDefaultpreventDefault 阻止了浏览器视觉上更新输入,即使checked被触发。变通的方式是要么移除preventDefault的调用,要么把checked 的触发放在一个setTimeout里。

-

不受控组件 #

-

一个没有 value 属性的 <input> 是一个不受控组件:

-
  render: function() {
-    return <input type="text" />;
-  }
-
-

上面的代码将渲染出一个空值的输入框,用户输入将立即反应到元素上。和受控元素一样,使用 onChange 事件可以监听值的变化。

- -

不受控组件维持它自己的内部状态。

-

默认值 #

-

如果想给组件设置一个非空的初始值,可以使用 defaultValue 属性。例如:

-
  render: function() {
-    return <input type="text" defaultValue="Hello!" />;
-  }
-
-

这个例子会像上面的 受控组件 例子一样运行。

- -

同样的, <input type="checkbox"><input type="radio"> 支持 defaultChecked<select> 支持 defaultValue.

- -
-

注意:

- -

defaultValuedefaultChecked props 只能在内部渲染时被使用。 如果你需要在随后的渲染更新值, 你需要使用 受控组件.

-
-

高级主题 #

为什么使用受控组件? #

-

在 React 中使用诸如 <input> 的表单组件时,遇到了一个在传统 HTML 中没有的挑战。比如下面的代码:

-
  <input type="text" name="title" value="Untitled" />
-
-

它渲染一个初始值Untitled 的输入框。当用户改变输入框的值时,节点的 value 属性( property)将随之变化,但是 node.getAttribute('value') 还是会返回初始设置的值 Untitled.

- -

与 HTML 不同,React 组件必须在任何时间点表现视图的状态,而不仅仅是在初始化时。比如在 React 中:

-
  render: function() {
-    return <input type="text" name="title" value="Untitled" />;
-  }
-
-

由于这个方法描述了在任意时间点上的视图,那么文本输入框的值就应该始终Untitled

-

为什么 <textarea> 使用 value 属性? #

-

在 HTML 中, <textarea> 的值通常使用子节点设置:

-
  <!-- 反例:在 React 中不要这样使用! -->
-  <textarea name="description">This is the description.</textarea>
-
-

对 HTML 而言,让开发者设置多行的值很容易。但是,由于 React 是 JavaScript,没有字符串限制,可以使用 \n 实现换行。简言之,React 已经有 valuedefaultValue 属性,<textarea> 组件的子节点扮演什么角色就有点模棱两可了。基于此, 设置 <textarea> 值时不应该使用子节点:

-
  <textarea name="description" value="This is a description." />
-
-

如果 非要 使用子节点,效果和使用 defaultValue 一样。

-

为什么 <select> 使用 value 属性 #

-

HTML 中 <select> 通常使用 <option>selected 属性设置选中状态;React 为了更方便地控制组件,采用以下方式代替:

-
  <select value="B">
-    <option value="A">Apple</option>
-    <option value="B">Banana</option>
-    <option value="C">Cranberry</option>
-  </select>
-
-

如果是不受控组件,则使用 defaultValue

- -
-

注意:

- -

value 属性传递一个数组,可以选中多个选项:<select multiple={true} value={['B', 'C']}>

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/forms.html b/docs/forms.html index eeaec11e50..5ba02f7e14 100644 --- a/docs/forms.html +++ b/docs/forms.html @@ -1,12 +1,14 @@ + + - Forms | React - - + Forms - React + + @@ -44,400 +46,33 @@
- - - -
- -
+ +
+ +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Primi Passi -

-
- -

JSFiddle #

-

La maniera più semplice di cominciare ad hackerare con React è usare i seguenti esempi di Hello World su JSFiddle:

- - -

Starter Kit #

-

Scarica lo starter kit per cominciare.

- - - -

Nella directory principale dello starter kit, crea helloworld.html con il seguente contenuto.

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Ciao React!</title>
-    <script src="build/react.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-      ReactDOM.render(
-        <h1>Cial, mondo!</h1>,
-        document.getElementById('example')
-      );
-    </script>
-  </body>
-</html>
-
-

La sintassi XML all'interno di JavaScript è chiamata JSX; dài un'occhiata alla sintassi JSX per saperne di più. Allo scopo di tradurla in puro JavaScript usiamo <script type="text/babel"> e includiamo Babel per effettuare la trasformazione effettiva nel browser.

-

File Separato #

-

Il tuo codice React JSX può trovarsi in un file a parte. Crea il seguente src/helloworld.js.

-
ReactDOM.render(
-  <h1>Ciao, mondo!</h1>,
-  document.getElementById('example')
-);
-
-

Quindi fai riferimento ad esso da helloworld.html:

-
<script type="text/babel" src="src/helloworld.js"></script>
-
-

Nota che in alcuni browsers (Chrome, ad esempio) falliranno nel caricamento del file a meno che non sia servito tramite HTTP.

-

Trasformazione Offline #

-

Anzitutto installa gli strumenti da riga di comando di Babel (è richiesto npm):

-
npm install --global babel
-
-

Quindi, traduci il tuo file src/helloworld.js a semplice JavaScript:

-
babel src --watch --out-dir build
-
-

Il file build/helloworld.js è generato automaticamente ogni qualvolta effettui un cambiamento. Leggi la documentazione di Babel CLI per un uso più avanzato.

-
ReactDOM.render(
-  React.createElement('h1', null, 'Ciao, mondo!'),
-  document.getElementById('example')
-);
-
-

Aggiorna il tuo file HTML come segue:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Ciao React!</title>
-    <script src="build/react.js"></script>
-    <!-- Non c'è bisogno di Babel! -->
-  </head>
-  <body>
-    <div id="example"></div>
-    <script src="build/helloworld.js"></script>
-  </body>
-</html>
-

Vuoi CommonJS? #

-

Se vuoi usare React con browserify, webpack, o un altro sistema modulare compatibile con CommonJS, usa il pacchetto npm react. In aggiunta, lo strumento di build jsx può essere integrato in quasi tutti i sistemi di packaging (non soltanto CommonJS) assai facilmente.

-

Passi Successivi #

-

Dài un'occhiata al tutorial e agli altri esempi nella directory examples dello starter kit per saperne di più.

- -

Abbiamo anche un wiki al quale la comunità contribuisce con flussi di lavoro, componenti UI, routing, gestione dati etc.

- -

In bocca al lupo, e benvenuto/a!

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/getting-started-ja-JP.html b/docs/getting-started-ja-JP.html deleted file mode 100644 index 873a9df3e6..0000000000 --- a/docs/getting-started-ja-JP.html +++ /dev/null @@ -1,577 +0,0 @@ - - - - - - - 始めてみましょう | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 始めてみましょう -

-
- -

JSFiddle #

-

React でのハッキングを始めるにあたり、一番簡単なものとして次の JSFiddle で動いている Hello World の例を取り上げます。

- - -

スターターキット #

-

始めるためにスターターキットをダウンロードしましょう。

- - - -

スターターキットのルートディレクトリに helloworld.html を作り、次のように書いてみましょう。

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="build/react.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-      ReactDOM.render(
-        <h1>Hello, world!</h1>,
-        document.getElementById('example')
-      );
-    </script>
-  </body>
-</html>
-
-

JavaScript の中に書かれた XML シンタックスは JSX と呼ばれるものです(JSX の詳しいことについては JSX syntax を読んでください)。ここでは JSX から vanilla JavaScript への変換をブラウザ内で行わせるため、先程のコードには <script type="text/jsx"> と書いており、加えて JSXTransformer.js を読み込ませています。

-

ファイルの分割 #

-

React の JSX コードは別ファイルに分離することができます。 次のような src/helloworld.js を作ってみましょう。

-
ReactDOM.render(
-  <h1>Hello, world!</h1>,
-  document.getElementById('example')
-);
-
-

それが終わったら、helloworld.js への参照を helloworld.html に書き込みましょう。

-
<script type="text/babel" src="src/helloworld.js"></script>
-

オフラインでの変換 #

-

まずはコマンドラインツールをインストールしましょう(npm が必要です)。

-
npm install -g react-tools
-
-

インストールが終わったら、先程書いた src/helloworld.js ファイルを生の JavaScript に変換してみましょう。

-
jsx --watch src/ build/
-
-

すると、src/helloword.js に変更を加えるごとに build/helloworld.js が自動で生成されるようになります。

-
ReactDOM.render(
-  React.createElement('h1', null, 'Hello, world!'),
-  document.getElementById('example')
-);
-
-

最後に HTML ファイルを以下のように書き換えましょう。

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="build/react.js"></script>
-    <!-- Babel は必要ありません! -->
-  </head>
-  <body>
-    <div id="example"></div>
-    <script src="build/helloworld.js"></script>
-  </body>
-</html>
-

CommonJS を使うには #

-

React を browserifywebpack、または CommonJS 準拠の他のモジュールシステムと一緒に使いたい場合、 react npm package を使ってみてください。また、jsx ビルドツールをパッケージングシステム(CommonJS に限らず)に導入することも非常に簡単です。

-

次にすること #

-

チュートリアル や、スターターキットの examples ディレクトリに入っている他の例を読んでみてください。

- -

また、ワークフロー、UIコンポーネント、ルーティング、データマネジメントなどの方面で貢献しているコミュニティの wiki もあります。

- -

幸運を祈ります!React へようこそ!

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/getting-started-ko-KR.html b/docs/getting-started-ko-KR.html deleted file mode 100644 index e6053f44d7..0000000000 --- a/docs/getting-started-ko-KR.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - - - 시작해보기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 시작해보기 -

-
- -

JSFiddle #

-

React를 시작하는 가장 빠른 방법은 다음의 Hello World JSFiddle 예제를 따라 해 보는 것입니다.

- - -

npm으로 React 사용하기 #

-

browserify, webpack 같은 CommonJS 모듈 시스템과 함께 React를 사용하시는 것을 권장합니다. react, react-dom npm 패키지를 사용하세요.

-
// main.js
-var React = require('react');
-var ReactDOM = require('react-dom');
-
-ReactDOM.render(
-  <h1>Hello, world!</h1>,
-  document.getElementById('example')
-);
-
-

browserify를 설치한 후에 React DOM을 설치하고 bundle을 빌드합니다.

-
$ npm install --save react react-dom babelify babel-preset-react
-$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
-
-
-

주의:

- -

ES2015를 사용하고 있다면, babel-preset-es2015 패키지도 설치할 필요가 있습니다.

-
-

npm 없이 Quick Start 하기 #

-

만약 당신이 npm을 사용할 준비가 아직 안되었다면, 미리빌드된 React와 React DOM 파일이 포함된 초심자용 키트를 다운로드 받을 수 있습니다.

- - - -

초심자용 키트의 최상위 디렉터리에 아래의 내용대로 helloworld.html 파일을 생성합니다.

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="build/react.js"></script>
-    <script src="build/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-      ReactDOM.render(
-        <h1>Hello, world!</h1>,
-        document.getElementById('example')
-      );
-    </script>
-  </body>
-</html>
-
-

JavaScript 안에 보이는 XML 구문은 JSX라고 합니다; 더 자세한 내용은 JSX syntax을 확인하세요. 일반적인 JavaScript로 번역하기 위해 <script type="text/babel">를 사용하고 Babel을 포함하는 것으로 실제로 브라우저에서 변환작업을 수행합니다.

-

파일의 분리 #

-

React JSX 코드는 분리된 파일로 존재할 수 있습니다. 다음 내용으로 src/helloworld.js를 생성해보세요.

-
ReactDOM.render(
-  <h1>Hello, world!</h1>,
-  document.getElementById('example')
-);
-
-

그다음 helloworld.html에서 참조합니다:

-
<script type="text/babel" src="src/helloworld.js"></script>
-
-

크롬 같은 몇몇 브라우저에서는 HTTP를 통해 제공되는 파일이 아니면 로드에 실패하므로 주의하세요.

-

오프라인 변환 #

-

먼저 Babel 커맨드라인 도구를 설치합니다. (npm 필요):

-
npm install --global babel-cli
-npm install babel-preset-react
-
-

그다음, src/helloworld.js 파일을 일반 JavaScript 파일로 변환합니다:

-
babel --presets react src --watch --out-dir build
-
-
-

주의:

- -

ES2015를 사용하고 있다면, babel-preset-es2015 패키지도 설치할 필요가 있습니다.

-
- -

수정할 때마다 build/helloworld.js 파일이 자동생성됩니다. 더 자세한 사용법은 Babel CLI 문서를 읽어보세요.

-
ReactDOM.render(
-  React.createElement('h1', null, 'Hello, world!'),
-  document.getElementById('example')
-);
-
-

아래의 내용대로 HTML 파일을 업데이트합니다:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="build/react.js"></script>
-    <script src="build/react-dom.js"></script>
-    <!-- Babel은 이제 불필요합니다! -->
-  </head>
-  <body>
-    <div id="example"></div>
-    <script src="build/helloworld.js"></script>
-  </body>
-</html>
-

다음 단계로 #

-

더 알아보려면 튜토리얼과 초심자용 키트의 examples 디렉터리에서 다른 예제들을 확인해 보세요.

- -

커뮤니티의 기여로 운영되는 Wiki도 있습니다: 워크플로우, UI 컴포넌트, 라우팅, 데이터 관리 등

- -

React의 세계에 오신 것을 환영합니다. 행운을 빌어요!

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/getting-started-zh-CN.html b/docs/getting-started-zh-CN.html deleted file mode 100644 index 382a40a686..0000000000 --- a/docs/getting-started-zh-CN.html +++ /dev/null @@ -1,617 +0,0 @@ - - - - - - - 入门教程 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 入门教程 -

-
- -

JSFiddle #

-

开始 Hack React 的最简单的方法是用下面 JSFiddle 的Hello Worlds:

- - -

通过 npm 使用 React #

-

我们建议在 React 中使用 CommonJS 模块系统,比如 browserifywebpack。使用 reactreact-dom npm 包.

-
// main.js
-var React = require('react');
-var ReactDOM = require('react-dom');
-
-ReactDOM.render(
-  <h1>Hello, world!</h1>,
-  document.getElementById('example')
-);
-
-

要用 browserify 安装 React DOM 和构建你的包。

-
$ npm install --save react react-dom babelify babel-preset-react
-$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
-
-

要用 webpack 安装 React DOM 和构建你的包:

-
$ npm install --save react react-dom babel-preset-react
-$ webpack
-
-
-

注意:

- -

如果你正在使用 ES2015, 你将要使用 babel-preset-es2015 包.

-
- -

注意: 默认情况下,React 将会在开发模式,很缓慢,不建议用于生产。要在生产模式下使用 React,设置环境变量 NODE_ENVproduction (使用 envify 或者 webpack's DefinePlugin)。例如:

-
new webpack.DefinePlugin({
-  "process.env": {
-    NODE_ENV: JSON.stringify("production")
-  }
-});
-

不用 npm 的快速开始 #

-

如果你现在还没准备要使用npm,你可以下载这个已经包含了预构建的 React 和 React DOM 拷贝的入门套件.

- - - -

在入门教程包的根目录,创建一个含有如下代码的 helloworld.html

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="build/react.js"></script>
-    <script src="build/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-      ReactDOM.render(
-        <h1>Hello, world!</h1>,
-        document.getElementById('example')
-      );
-    </script>
-  </body>
-</html>
-
-

在 JavaScript 代码里写着 XML 格式的代码称为 JSX;可以去 JSX 语法 里学习更多 JSX 相关的知识。为了把 JSX 转成标准的 JavaScript,我们用 <script type="text/babel"> 标签,并引入 Babel 来完成在浏览器里的代码转换。在浏览器里打开这个html,你应该可以看到成功的消息!

-

分离文件 #

-

你的 React JSX 代码文件可以写在另外的文件里。新建下面的 src/helloworld.js

-
ReactDOM.render(
-  <h1>Hello, world!</h1>,
-  document.getElementById('example')
-);
-
-

然后在 helloworld.html 引用该文件:

-
<script type="text/babel" src="src/helloworld.js"></script>
-
-

注意一些浏览器(比如 Chrome )会在使用 HTTP 以外的协议加载文件时失败。

-

离线转换 #

-

先安装Babel命令行工具(需要 npm):

-
npm install --global babel-cli
-npm install babel-preset-react
-
-

然后把你的 src/helloworld.js 文件转成标准的 JavaScript:

-
babel --presets react src --watch --out-dir build
-
-
-

注意:

- -

如果你正在使用 ES2015, 你将需要使用 babel-preset-es2015 包.

-
- -

build/helloworld.js 会在你对文件进行修改时自动生成。 阅读 Babel CLI 文档 了解高级用法。

-
ReactDOM.render(
-  React.createElement('h1', null, 'Hello, world!'),
-  document.getElementById('example')
-);
-
-

对照下面更新你的 HTML 代码

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="build/react.js"></script>
-    <script src="build/react-dom.js"></script>
-    <!-- 不需要 Babel! -->
-  </head>
-  <body>
-    <div id="example"></div>
-    <script src="build/helloworld.js"></script>
-  </body>
-</html>
-

下一步 #

-

去看看入门教程 和入门教程包 examples 目录下的其它例子学习更多。

- -

我们还有一个社区开发者共建的 Wiki:workflows, UI-components, routing, data management etc.

- -

恭喜你,欢迎来到 React 的世界。

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/getting-started.html b/docs/getting-started.html deleted file mode 100644 index 3d57280c70..0000000000 --- a/docs/getting-started.html +++ /dev/null @@ -1,555 +0,0 @@ - - - - - - - Getting Started | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Getting Started -

-
- -

JSFiddle #

-

The easiest way to start hacking on React is using the following JSFiddle Hello World examples:

- - -

Create React App #

-

Create React App is a new officially supported way to create single-page React applications. It offers a modern build setup with no configuration. It requires Node 4 or higher.

- -

Note that it has some limitations and is only useful for single-page applications. If you need more flexibility, or if you want to integrate React into an existing project, consider other options below.

-

Starter Pack #

-

If you're just getting started, you can download the starter kit. The starter kit includes prebuilt copies of React and React DOM for the browser, as well as a collection of usage examples to help you get started.

- - - -

In the root directory of the starter kit, create a helloworld.html with the following contents.

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="build/react.js"></script>
-    <script src="build/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-      ReactDOM.render(
-        <h1>Hello, world!</h1>,
-        document.getElementById('example')
-      );
-    </script>
-  </body>
-</html>
-
-

The XML syntax inside of JavaScript is called JSX; check out the JSX syntax to learn more about it. In order to translate it to vanilla JavaScript we use <script type="text/babel"> and include Babel to actually perform the transformation in the browser. Open the html from a browser and you should already be able to see the greeting!

-

Separate File #

-

Your React JSX code can live in a separate file. Create the following src/helloworld.js.

-
ReactDOM.render(
-  <h1>Hello, world!</h1>,
-  document.getElementById('example')
-);
-
-

Then reference it from helloworld.html:

-
<script type="text/babel" src="src/helloworld.js"></script>
-
-

Note that some browsers (Chrome, e.g.) will fail to load the file unless it's served via HTTP.

-

Using React with npm or Bower #

-

You can also use React with package managers like npm or Bower. You can learn more in our Package Managers section.

-

Next Steps #

-

Check out the tutorial and the other examples in the starter kit's examples directory to learn more.

- -

Good luck, and welcome!

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/glossary-it-IT.html b/docs/glossary-it-IT.html deleted file mode 100644 index d5025b8732..0000000000 --- a/docs/glossary-it-IT.html +++ /dev/null @@ -1,618 +0,0 @@ - - - - - - - Terminologia del DOM (Virtuale) | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Terminologia del DOM (Virtuale) -

-
- -

Nella terminologia di React, esistono cinque tipi base che è importante distinguere:

- - -

Elementi React #

-

Il tipo primario in React è il ReactElement. Possiede quattro proprietà: type, props, key e ref. Non possiede alcun metodo e non espone nulla sul prototype.

- -

Puoi creare uno di questi oggetti attraverso React.createElement.

-
var root = React.createElement('div');
-
-

Per effettuare il rendering di un nuovo albero nel DOM, crei dei ReactElement ande li passi a ReactDOM.render assieme a un Element DOM regolare (HTMLElement o SVGElement). I ReactElement non vanno confusi con gli Element del DOM. Un ReactElement è una rappresentazione leggera, priva di stato, immutabile e virtuale di un Element del DOM. È un DOM virtuale.

-
ReactDOM.render(root, document.getElementById('example'));
-
-

Per aggiungere proprietà ad un elemento DOM, passa un oggetto di proprietà come secondo argomento, e i figli come terzo argomento.

-
var child = React.createElement('li', null, 'Contenuto di Testo');
-var root = React.createElement('ul', { className: 'my-list' }, child);
-ReactDOM.render(root, document.getElementById('example'));
-
-

Se usi React JSX, allora questi ReactElement verranno creati per te. Questa espressione è equivalente:

-
var root = <ul className="my-list">
-             <li>Contenuto di Testo</li>
-           </ul>;
-ReactDOM.render(root, document.getElementById('example'));
-

Le Factory #

-

Una factory di ReactElement è semplicemente una funzione che genera un ReactElement con una particolare proprietà type. React ha uno helper integrato per permetterti di creare factory. La sua implementazione è semplicemente:

-
function createFactory(type) {
-  return React.createElement.bind(null, type);
-}
-
-

Ti permette di creare una conveniente scorciatoia anziché scrivere ogni volta React.createElement('div').

-
var div = React.createFactory('div');
-var root = div({ className: 'my-div' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React possiede già factory integrate per tag HTML comuni:

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Contenuto di Testo')
-           );
-
-

Se stai usando JSX non hai bisogno di factory. JSX fornisce già una conveniente scorciatoia per creare ReactElement.

-

Nodi React #

-

Un ReactNode può essere uno tra:

- -
    -
  • ReactElement
  • -
  • string (ovvero ReactText)
  • -
  • number (ovvero ReactText)
  • -
  • Array di ReactNode (ovvero ReactFragment)
  • -
- -

Questi sono usati come proprietà di altri ReactElement per rappresentare i figli. Effettivamente creano un albero di ReactElement.

-

Componenti React #

-

Puoi usare React usando soltanto ReactElement, ma per avvantaggiarti seriamente di React vorrai usare i ReactComponent per creare incapsulamento con uno stato incluso.

- -

Una classe ReactComponent è semplicemente una classe JavaScript (o una "funzione costruttore").

-
var MyComponent = React.createClass({
-  render: function() {
-    ...
-  }
-});
-
-

Quando questo costruttore è invocato, ci si aspetta che restituisca un oggetto con almeno un metodo render. Questo oggetto è chiamato ReactComponent.

-
var component = new MyComponent(props); // non farlo mai!
-
-

Per scopi diversi dai test, non chiamerai mai questo costruttore direttamente. React lo chiamerà per te.

- -

Invece, passa una classe ReactComponent a createElement per ottenere un ReactElement.

-
var element = React.createElement(MyComponent);
-
-

OPPURE usando JSX:

-
var element = <MyComponent />;
-
-

Quando element viene passato a ReactDOM.render, React chiamerà il costruttore al tuo posto e creerà unReactComponent, che verrà restituito.

-
var component = ReactDOM.render(element, document.getElementById('example'));
-
-

Se chiami ripetutamente ReactDOM.render con lo stesso tipo di ReactElement e lo stesso Element DOM come contenitore, ti restituirà sempre la stessa istanza. Questa istanza è dotata di stato.

-
var componentA = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-var componentB = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-componentA === componentB; // true
-
-

Questo è il motivo per cui non dovresti mai costruire la tua istanza. Invece, ReactElement è un ReactComponent virtuale prima che venga costruito. Un vecchio ReactElement e uno nuovo possono essere confrontati per vedere se una nuova istanza di ReactComponent è stata creata o quella esistente è stata riutilizzata.

- -

Ci si aspetta che il metodo render di un ReactComponent restituisca un altro ReactElement. Ciò permette a questi componenti di essere composti. In ultima analisi, il rendering si risolve in un ReactElement con un tag string che viene istanziato come un Element DOM e viene inserito nel documento.

-

Definizioni Formali dei Tipi #

Punto di Entrata #

ReactDOM.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
-

Nodi ed Elementi #

type ReactNode = ReactElement | ReactFragment | ReactText;
-
-type ReactElement = ReactComponentElement | ReactDOMElement;
-
-type ReactDOMElement = {
-  type : string,
-  props : {
-    children : ReactNodeList,
-    className : string,
-    etc.
-  },
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactComponentElement<TProps> = {
-  type : ReactClass<TProps>,
-  props : TProps,
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactFragment = Array<ReactNode | ReactEmpty>;
-
-type ReactNodeList = ReactNode | ReactEmpty;
-
-type ReactText = string | number;
-
-type ReactEmpty = null | undefined | boolean;
-

Classi e Componenti #

type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;
-
-type ReactComponent<TProps> = {
-  props : TProps,
-  render : () => ReactElement
-};
-
- -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/glossary-ko-KR.html b/docs/glossary-ko-KR.html deleted file mode 100644 index a4e7045234..0000000000 --- a/docs/glossary-ko-KR.html +++ /dev/null @@ -1,618 +0,0 @@ - - - - - - - React (가상) DOM 용어 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- React (가상) DOM 용어 -

-
- -

다음은 React에서 사용되는 용어들로, 이 다섯 가지의 타입을 구별하는 것은 중요합니다.

- - -

React 엘리먼트 #

-

ReactElement는 React의 주요 타입입니다. type, props, key, ref의 네 가지 프로퍼티를 가집니다. 메소드는 가지지 않으며 프로토타입에는 아무 것도 들어있지 않습니다.

- -

이러한 객체는 React.createElement를 통해 만들 수 있습니다.

-
var root = React.createElement('div');
-
-

DOM에 새로운 트리를 렌더링하기 위해서는 ReactElement를 만들고 일반적인 DOM Element (HTMLElement 또는 SVGElement)와 함께 ReactDOM.render에 넘깁니다. ReactElement를 DOM Element와 혼동해서는 안됩니다. ReactElement는 가볍고, 상태를 갖지 않으며, 변경 불가능한, DOM Element의 가상 표현입니다. 즉 가상 DOM입니다.

-
ReactDOM.render(root, document.getElementById('example'));
-
-

DOM 엘리먼트에 프로퍼티를 추가하려면 두번째 인자로 프로퍼티 객체를, 세번째 인자로 자식을 넘깁니다.

-
var child = React.createElement('li', null, 'Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child);
-ReactDOM.render(root, document.getElementById('example'));
-
-

React JSX를 사용하면 ReactElement가 알아서 만들어집니다. 따라서 다음 코드는 앞의 코드와 같습니다:

-
var root = <ul className="my-list">
-             <li>Text Content</li>
-           </ul>;
-ReactDOM.render(root, document.getElementById('example'));
-

팩토리 #

-

ReactElement 팩토리는 그저 특정한 type 프로퍼티를 가지는 ReactElement를 만들어주는 함수입니다. React에는 팩토리를 만드는 헬퍼가 내장되어 있습니다. 그 함수는 사실상 다음과 같습니다:

-
function createFactory(type) {
-  return React.createElement.bind(null, type);
-}
-
-

이를 이용하면 편리한 단축 함수를 만들 수 있어 항상 React.createElement('div')를 입력하지 않아도 됩니다.

-
var div = React.createFactory('div');
-var root = div({ className: 'my-div' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React에는 이미 보통의 HTML 태그를 위한 팩토리가 내장되어 있습니다:

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
-

JSX를 사용하면 팩토리가 필요하지 않습니다. 이미 JSX가 ReactElement를 만드는 편리한 단축 문법을 제공합니다.

-

React 노드 #

-

ReactNode는 다음 중 하나가 될 수 있습니다:

- -
    -
  • ReactElement
  • -
  • string (ReactText로 부르기도 함)
  • -
  • number (ReactText로 부르기도 함)
  • -
  • ReactNode의 배열 (ReactFragment로 부르기도 함)
  • -
- -

이들은 자식을 표현하기 위해 다른 ReactElement의 프로퍼티에 사용됩니다. 사실상 이들이 ReactElement의 트리를 형성합니다.

-

React 컴포넌트 #

-

ReactElement만 가지고도 React를 사용할 수는 있지만, React의 장점을 제대로 활용하려면 ReactComponent를 사용하여 상태를 가진 캡슐화된 객체를 만들기를 원할 것입니다.

- -

ReactComponent 클래스는 그냥 JavaScript 클래스 (또는 "생성자 함수")입니다.

-
var MyComponent = React.createClass({
-  render: function() {
-    ...
-  }
-});
-
-

이 생성자가 호출될 때 최소한 render 메소드를 가진 객체를 리턴해야 합니다. 이 리턴된 객체를 ReactComponent라고 부릅니다.

-
var component = new MyComponent(props); // 절대 하지 마세요.
-
-

테스트 목적이 아니라면 절대 이 생성자를 직접 호출하지 마십시오. React가 알아서 호출해줍니다.

- -

대신 ReactComponent 클래스를 createElement에 넘겨 ReactElement를 받을 수 있습니다.

-
var element = React.createElement(MyComponent);
-
-

또는 JSX를 사용하면:

-
var element = <MyComponent />;
-
-

이것이 ReactDOM.render에 넘겨지면 React가 알아서 생성자를 호출하여 ReactComponent를 만들고 리턴합니다.

-
var component = ReactDOM.render(element, document.getElementById('example'));
-
-

같은 타입의 ReactElement와 같은 컨테이너 DOM Element를 가지고 ReactDOM.render를 계속 호출하면 항상 같은 인스턴스를 리턴합니다. 이 인스턴스는 상태를 가집니다.

-
var componentA = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-var componentB = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-componentA === componentB; // true
-
-

그렇기 때문에 직접 인스턴스를 만들어서는 안됩니다. ReactComponent가 생성되기 전에 ReactElement가 대신 가상의 ReactComponent 역할을 합니다. 이전 ReactElement와 새 ReactElement를 비교하여 새로운 ReactComponent를 만들지, 아니면 기존 것을 재사용할지 결정합니다.

- -

ReactComponentrender 메소드는 또다른 ReactElement를 리턴해야 합니다. 이렇게 해서 컴포넌트들이 조합됩니다. 결과적으로 렌더링 과정은 다음과 같습니다. string 타입의 태그를 가진 ReactElement를 통해 DOM Element 인스턴스가 생성되며 문서에 삽입됩니다.

-

형식 타입 정의 #

진입점 #

ReactDOM.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
-

노드와 엘리먼트 #

type ReactNode = ReactElement | ReactFragment | ReactText;
-
-type ReactElement = ReactComponentElement | ReactDOMElement;
-
-type ReactDOMElement = {
-  type : string,
-  props : {
-    children : ReactNodeList,
-    className : string,
-    etc.
-  },
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactComponentElement<TProps> = {
-  type : ReactClass<TProps>,
-  props : TProps,
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactFragment = Array<ReactNode | ReactEmpty>;
-
-type ReactNodeList = ReactNode | ReactEmpty;
-
-type ReactText = string | number;
-
-type ReactEmpty = null | undefined | boolean;
-

클래스와 컴포넌트 #

type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;
-
-type ReactComponent<TProps> = {
-  props : TProps,
-  render : () => ReactElement
-};
-
- -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/glossary-zh-CN.html b/docs/glossary-zh-CN.html deleted file mode 100644 index 04df569804..0000000000 --- a/docs/glossary-zh-CN.html +++ /dev/null @@ -1,618 +0,0 @@ - - - - - - - React (虚拟) DOM 术语 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- React (虚拟) DOM 术语 -

-
- -

在 React 的术语中,有五个要重点区分的核心类型:

- - -

React Elements(React 元素) #

-

React里的首要类型是 ReactElement.它有四个 properties:type, props, keyref.它没有方法,在 prototype 上什么也没有.

- -

你可以通过 React.createElement 来创建这些对象.

-
var root = React.createElement('div');
-
-

要渲染一个新的树到DOM上,你创建 ReactElements 并传递他们到 ReactDOM.render 伴随着一个标准的 DOM Element (HTMLElementSVGElement).ReactElements 不要与 DOM Elements 混淆.ReactElement 是一个轻的,有状态的,不可变的,虚拟的DOM Element 的表达.它是一个虚拟 DOM.

-
ReactDOM.render(root, document.getElementById('example'));
-
-

要给一个DOM元素添加 properties,传递一个properties 对象作为第二个参数,第三个参数传递子级.

-
var child = React.createElement('li', null, 'Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child);
-ReactDOM.render(root, document.getElementById('example'));
-
-

如果你使用 React JSX,这些ReactElements 已经为你创建了.所以 这是等价的:

-
var root = <ul className="my-list">
-             <li>Text Content</li>
-           </ul>;
-ReactDOM.render(root, document.getElementById('example'));
-

Factories(工厂) #

-

ReactElement-工厂 是一个产生特定 type property的 ReactElement 的函数.React有一个为你内建的辅助工具来创建工厂.它想这样起作用:

-
function createFactory(type) {
-  return React.createElement.bind(null, type);
-}
-
-

它允许你创建一个方便的速记 来代替每次输入 React.createElement('div') .

-
var div = React.createFactory('div');
-var root = div({ className: 'my-div' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React 已经具备用于常用 HTML tags的内建工厂

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
-

如果你使用JSX 你没有必要使用工厂.JSX已经为创建 ReactElements 提供了一个 方便的速记.

-

React Nodes #

-

一个 ReactNode 可以是:

- -
    -
  • ReactElement
  • -
  • string (aka ReactText)
  • -
  • number (aka ReactText)
  • -
  • Array of ReactNodes (aka ReactFragment)
  • -
- -

他们被用作其他ReactElements的properties来表示子级.事实上他们创建了一个 ReactElements 的树.

-

React Components #

-

你可以使用 React只使用ReactElements 但是要真正利用React,你将要使用 ReactComponents 来创建内嵌 state 的封装.

- -

一个 ReactComponent 类就是一个 JavaScript 类 (或者 "constructor function").

-
var MyComponent = React.createClass({
-  render: function() {
-    ...
-  }
-});
-
-

当这个构造函数被调用,期望返回一个至少有一个 render 方法的对象.这个对象被称为一个 ReactComponent.

-
var component = new MyComponent(props); // never do this
-
-

与测试不同,你可能通常 绝不会 亲自调用这个构造函数.React 为你调用它.

- -

作为替代,你传递 ReactComponent 类到 createElement,你得到一个 ReactElement.

-
var element = React.createElement(MyComponent);
-
-

或者用 JSX:

-
var element = <MyComponent />;
-
-

当这个被传给 ReactDOM.render,React 会为你调用构造函数并创建一个 ReactComponent,返回给你.

-
var component = ReactDOM.render(element, document.getElementById('example'));
-
-

如果你保持用相同类型的 ReactElement 和相同的DOM Element容器调用 ReactDOM.render ,它总是会返回相同的实例.这个实例是状态化的.

-
var componentA = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-var componentB = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-componentA === componentB; // true
-
-

这就是为什么你不应该构造你自己的实例.作为替代,ReactElement 在它被构造以前 是一个虚拟的 ReactComponent.一个老的和新的ReactElement 可以被比较来判断 一个新的 ReactComponent 实例是否需要被创建或者已经存在的是否应该被重用.

- -

ReactComponentrender 方法被期望返回另一个 ReactElement.这允许这些组件被结构化.最后,渲染分解为 带着一个 string tag的ReactElement,它实例化一个 DOM Element 实例并把它插入document里.

-

Formal Type Definitions #

Entry Point #

ReactDOM.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
-

Nodes and Elements #

type ReactNode = ReactElement | ReactFragment | ReactText;
-
-type ReactElement = ReactComponentElement | ReactDOMElement;
-
-type ReactDOMElement = {
-  type : string,
-  props : {
-    children : ReactNodeList,
-    className : string,
-    etc.
-  },
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactComponentElement<TProps> = {
-  type : ReactClass<TProps>,
-  props : TProps,
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactFragment = Array<ReactNode | ReactEmpty>;
-
-type ReactNodeList = ReactNode | ReactEmpty;
-
-type ReactText = string | number;
-
-type ReactEmpty = null | undefined | boolean;
-

Classes and Components #

type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;
-
-type ReactComponent<TProps> = {
-  props : TProps,
-  render : () => ReactElement
-};
-
- -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/glossary.html b/docs/glossary.html index d69daef8d4..3535c23f10 100644 --- a/docs/glossary.html +++ b/docs/glossary.html @@ -1,622 +1,10 @@ - - - - - - React (Virtual) DOM Terminology | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- React (Virtual) DOM Terminology -

-
- -

In React's terminology, there are five core types that are important to distinguish:

- - -

React Elements #

-

The primary type in React is the ReactElement. It has four properties: type, props, key and ref. It has no methods and nothing on the prototype.

- -

You can create one of these objects through React.createElement.

-
var root = React.createElement('div');
-
-

To render a new tree into the DOM, you create ReactElements and pass them to ReactDOM.render along with a regular DOM Element (HTMLElement or SVGElement). ReactElements are not to be confused with DOM Elements. A ReactElement is a light, stateless, immutable, virtual representation of a DOM Element. It is a virtual DOM.

-
ReactDOM.render(root, document.getElementById('example'));
-
-

To add properties to a DOM element, pass a properties object as the second argument and children to the third argument.

-
var child = React.createElement('li', null, 'Text Content');
-var root = React.createElement('ul', { className: 'my-list' }, child);
-ReactDOM.render(root, document.getElementById('example'));
-
-

If you use React JSX, then these ReactElements are created for you. So this is equivalent:

-
var root = <ul className="my-list">
-             <li>Text Content</li>
-           </ul>;
-ReactDOM.render(root, document.getElementById('example'));
-

Factories #

-

A ReactElement-factory is simply a function that generates a ReactElement with a particular type property. React has a built-in helper for you to create factories. It's effectively just:

-
function createFactory(type) {
-  return React.createElement.bind(null, type);
-}
-
-

It allows you to create a convenient short-hand instead of typing out React.createElement('div') all the time.

-
var div = React.createFactory('div');
-var root = div({ className: 'my-div' });
-ReactDOM.render(root, document.getElementById('example'));
-
-

React already has built-in factories for common HTML tags:

-
var root = React.DOM.ul({ className: 'my-list' },
-             React.DOM.li(null, 'Text Content')
-           );
-
-

If you are using JSX you have no need for factories. JSX already provides a convenient short-hand for creating ReactElements.

-

React Nodes #

-

A ReactNode can be either:

- -
    -
  • ReactElement
  • -
  • string (aka ReactText)
  • -
  • number (aka ReactText)
  • -
  • Array of ReactNodes (aka ReactFragment)
  • -
- -

These are used as properties of other ReactElements to represent children. Effectively they create a tree of ReactElements.

-

React Components #

-

You can use React using only ReactElements but to really take advantage of React, you'll want to use ReactComponents to create encapsulations with embedded state.

- -

A ReactComponent Class is simply just a JavaScript class (or "constructor function").

-
var MyComponent = React.createClass({
-  render: function() {
-    ...
-  }
-});
-
-

When this constructor is invoked it is expected to return an object with at least a render method on it. This object is referred to as a ReactComponent.

-
var component = new MyComponent(props); // never do this
-
-

Other than for testing, you would normally never call this constructor yourself. React calls it for you.

- -

Instead, you pass the ReactComponent Class to createElement you get a ReactElement.

-
var element = React.createElement(MyComponent);
-
-

OR using JSX:

-
var element = <MyComponent />;
-
-

When this is passed to ReactDOM.render, React will call the constructor for you and create a ReactComponent, which is returned.

-
var component = ReactDOM.render(element, document.getElementById('example'));
-
-

If you keep calling ReactDOM.render with the same type of ReactElement and the same container DOM Element it always returns the same instance. This instance is stateful.

-
var componentA = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-var componentB = ReactDOM.render(<MyComponent />, document.getElementById('example'));
-componentA === componentB; // true
-
-

This is why you shouldn't construct your own instance. Instead, ReactElement is a virtual ReactComponent before it gets constructed. An old and new ReactElement can be compared to see if a new ReactComponent instance should be created or if the existing one should be reused.

- -

The render method of a ReactComponent is expected to return another ReactElement. This allows these components to be composed. Ultimately the render resolves into ReactElement with a string tag which instantiates a DOM Element instance and inserts it into the document.

- -

React 0.14 introduced stateless functional components as an alternative way of defining components. Instead of being a class, it is a simple function that accepts props and is expected to return a ReactElement.

-

Formal Type Definitions #

Entry Point #

ReactDOM.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
-

Nodes and Elements #

type ReactNode = ReactElement | ReactFragment | ReactText;
-
-type ReactElement = ReactComponentElement | ReactDOMElement;
-
-type ReactDOMElement = {
-  type : string,
-  props : {
-    children : ReactNodeList,
-    className : string,
-    etc.
-  },
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactComponentElement<TProps> = {
-  type : ReactClass<TProps> | ReactFunctionalComponent<TProps>,
-  props : TProps,
-  key : string | boolean | number | null,
-  ref : string | null
-};
-
-type ReactFragment = Array<ReactNode | ReactEmpty>;
-
-type ReactNodeList = ReactNode | ReactEmpty;
-
-type ReactText = string | number;
-
-type ReactEmpty = null | undefined | boolean;
-

Classes and Components #

type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;
-
-type ReactComponent<TProps> = {
-  props : TProps,
-  render : () => ReactElement
-};
-
-type ReactFunctionalComponent<TProps> = (TProps) => ReactElement;
-
- -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/handling-events.html b/docs/handling-events.html new file mode 100644 index 0000000000..edc566138a --- /dev/null +++ b/docs/handling-events.html @@ -0,0 +1,515 @@ + + + + + + + + + Handling Events - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Handling Events +

+
+ +

Handling events with React elements is very similar to handling events on DOM elements. There are some syntactic differences:

+ +
    +
  • React events are named using camelCase, rather than lowercase.
  • +
  • With JSX you pass a function as the event handler, rather than a string.
  • +
+ +

For example, the HTML:

+
<button onclick="activateLasers()">
+  Activate Lasers
+</button>
+
+

is slightly different in React:

+
<button onClick={activateLasers}>
+  Activate Lasers
+</button>
+
+

Another difference is that you cannot return false to prevent default behavior in React. You must call preventDefault explicitly. For example, with plain HTML, to prevent the default link behavior of opening a new page, you can write:

+
<a href="#" onclick="console.log('The link was clicked.'); return false">
+  Click me
+</a>
+
+

In React, this could instead be:

+
function ActionLink() {
+  function handleClick(e) {
+    e.preventDefault();
+    console.log('The link was clicked.');
+  }
+
+  return (
+    <a href="#" onClick={handleClick}>
+      Click me
+    </a>
+  );
+}
+
+

Here, e is a synthetic event. React defines these synthetic events according to the W3C spec, so you don't need to worry about cross-browser compatibility. See the SyntheticEvent reference guide to learn more.

+ +

When using React you should generally not need to call addEventListener to add listeners to a DOM element after it is created. Instead, just provide a listener when the element is initially rendered.

+ +

When you define a component using an ES6 class, a common pattern is for an event handler to be a method on the class. For example, this Toggle component renders a button that lets the user toggle between "ON" and "OFF" states:

+
class Toggle extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {isToggleOn: true};
+
+    // This binding is necessary to make `this` work in the callback
+    this.handleClick = this.handleClick.bind(this);
+  }
+
+  handleClick() {
+    this.setState(prevState => ({
+      isToggleOn: !prevState.isToggleOn
+    }));
+  }
+
+  render() {
+    return (
+      <button onClick={this.handleClick}>
+        {this.state.isToggleOn ? 'ON' : 'OFF'}
+      </button>
+    );
+  }
+}
+
+ReactDOM.render(
+  <Toggle />,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.toggle and pass it to onClick, this will be undefined when the function is actually called.

+ +

This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.

+ +

If calling bind annoys you, there are two ways you can get around this. If you are using the experimental property initializer syntax, you can use property initializers to correctly bind callbacks:

+
class LoggingButton extends React.Component {
+  // This syntax ensures `this` is bound within handleClick.
+  // Warning: this is *experimental* syntax.
+  handleClick = () => {
+    console.log('this is:', this);
+  }
+
+  render() {
+    return (
+      <button onClick={this.handleClick}>
+        Click me
+      </button>
+    );
+  }
+}
+
+

This syntax is enabled by default in Create React App.

+ +

If you aren't using property initializer syntax, you can use an arrow function in the callback:

+
class LoggingButton extends React.Component {
+  handleClick() {
+    console.log('this is:', this);
+  }
+
+  render() {
+    // This syntax ensures `this` is bound within handleClick
+    return (
+      <button onClick={(e) => this.handleClick(e)}>
+        Click me
+      </button>
+    );
+  }
+}
+
+

The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor to avoid this sort of performance problem.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/hello-world.html b/docs/hello-world.html new file mode 100644 index 0000000000..b02de562f6 --- /dev/null +++ b/docs/hello-world.html @@ -0,0 +1,418 @@ + + + + + + + + + Hello World - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Hello World +

+
+ +

The easiest way to get started with React is to use this Hello World example code on CodePen. You don't need to install anything; you can just open it in another tab and follow along as we go through examples. If you'd rather use a local development environment, check out the Installation page.

+ +

The smallest React example looks like this:

+
ReactDOM.render(
+  <h1>Hello, world!</h1>,
+  document.getElementById('root')
+);
+
+

It renders a header saying "Hello World" on the page.

+ +

The next few sections will gradually introduce you to using React. We will examine the building blocks of React apps: elements and components. Once you master them, you can create complex apps from small reusable pieces.

+

A Note on JavaScript #

+

React is a JavaScript library, and so it assumes you have a basic understanding of the JavaScript language. If you don't feel very confident, we recommend refreshing your JavaScript knowledge so you can follow along more easily.

+ +

We also use some of the ES6 syntax in the examples. We try to use it sparingly because it's still relatively new, but we encourage you to get familiar with arrow functions, classes, template literals, let, and const statements. You can use Babel REPL to check what ES6 code compiles to.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/index-ja-JP.html b/docs/index-ja-JP.html deleted file mode 100644 index 6a41a0c8ce..0000000000 --- a/docs/index-ja-JP.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting… - - -

Redirecting…

-Click here if you are not redirected. - - diff --git a/docs/index-ko-KR.html b/docs/index-ko-KR.html deleted file mode 100644 index 78a05a3c15..0000000000 --- a/docs/index-ko-KR.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting… - - -

Redirecting…

-Click here if you are not redirected. - - diff --git a/docs/index-zh-CN.html b/docs/index-zh-CN.html deleted file mode 100644 index e3ffa33deb..0000000000 --- a/docs/index-zh-CN.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting… - - -

Redirecting…

-Click here if you are not redirected. - - diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index a018abab66..0000000000 --- a/docs/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting… - - -

Redirecting…

-Click here if you are not redirected. - - diff --git a/docs/installation.html b/docs/installation.html new file mode 100644 index 0000000000..a243de35a0 --- /dev/null +++ b/docs/installation.html @@ -0,0 +1,442 @@ + + + + + + + + + Installation - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Installation +

+
+ +

React is flexible and can be used in a variety of projects. You can create new apps with it, but you can also gradually introduce it into an existing codebase without doing a rewrite.

+

Trying Out React #

+

If you're just interested in playing around with React, you can use CodePen. Try starting from this Hello World example code. You don't need to install anything; you can just modify the code and see if it works.

+ +

If you prefer to use your own text editor, you can also download this HTML file, edit it, and open it from the local filesystem in your browser. It does a slow runtime code transformation, so don't use it in production.

+

Creating a Single Page Application #

+

Create React App is the best way to starting building a new React single page application. It sets up your development environment so that you can use the latest JavaScript features, provides a nice developer experience, and optimizes your app for production.

+
npm install -g create-react-app
+create-react-app hello-world
+cd hello-world
+npm start
+
+

Create React App doesn't handle backend logic or databases; it just creates a frontend build pipeline, so you can use it with any backend you want. It uses Webpack, Babel and ESLint under the hood, but configures them for you.

+

Adding React to an Existing Application #

Using npm #

+

We recommend using React from npm with a bundler like Browserify or webpack. If you use npm for client package management, you can install React with:

+
npm install --save react react-dom
+
+

and import it from your code with something like:

+
import React from 'react';
+import ReactDOM from 'react-dom';
+
+ReactDOM.render(
+  <h1>Hello, world!</h1>,
+  document.getElementById('root')
+);
+
+

This code renders into an HTML element with the id of root so you need <div id="root"></div> somewhere in your HTML file. When you use React in this way, you should be transpiling your JavaScript using Babel with the es2015 and react presets. To use React in production mode, set the environment variable NODE_ENV to "production".

+ +

If you use Bower, React is available via the react package.

+

Enabling ES6 and JSX #

+

We recommend using React with Babel to let you use ES6 and JSX in your JavaScript code. ES6 is a set of modern JavaScript features that make development easier, and JSX is an extension to the JavaScript language that works nicely with React. The Babel setup instructions explain how to configure Babel in many different build environments. Make sure you install babel-preset-react and babel-preset-es2015 and enable them in your .babelrc, and you're good to go.

+

Using a CDN #

+

If you don't want to use npm to manage client packages, the react and react-dom npm packages also provide UMD distributions in dist folders, which are hosted on a CDN:

+
<script src="https://unpkg.com/react@15/dist/react.js"></script>
+<script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>
+
+

To load a specific version of react and react-dom, replace 15 with the version number.

+ +

Minified production versions of React are available at:

+
<script src="https://unpkg.com/react@15/dist/react.min.js"></script>
+<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
+
+ +
+ + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/interactivity-and-dynamic-uis-it-IT.html b/docs/interactivity-and-dynamic-uis-it-IT.html deleted file mode 100644 index 1fe5e6e677..0000000000 --- a/docs/interactivity-and-dynamic-uis-it-IT.html +++ /dev/null @@ -1,550 +0,0 @@ - - - - - - - Interattività e UI Dinamiche | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Interattività e UI Dinamiche -

-
- -

Hai già imparato a mostrare dati con React. Adesso vediamo come rendere le nostre UI interattive.

-

Un Esempio Semplice #

var LikeButton = React.createClass({
-  getInitialState: function() {
-    return {liked: false};
-  },
-  handleClick: function(event) {
-    this.setState({liked: !this.state.liked});
-  },
-  render: function() {
-    var text = this.state.liked ? 'mi piace' : 'non mi piace';
-    return (
-      <p onClick={this.handleClick}>
-        You {text} this. Click to toggle.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <LikeButton />,
-  document.getElementById('example')
-);
-

Gestione degli Eventi ed Eventi Sintetici #

-

Con React devi semplicemente passare il tuo gestore di eventi come una proprietà camelCased in modo simile a come faresti nel normale HTML. React si assicura che tutti gli eventi si comportano in maniera identica in IE8 e successivi implementando un sistema di eventi sintetici. Ovvero, React sa come propagare e catturare eventi secondo la specifica, e garantisce che gli eventi passati ai tuoi gestori di eventi siano consistenti con la specifica W3C, qualunque browser tu stia utilizzando.

-

Dietro le Quinte: Binding Automatico e Delega degli Eventi #

-

Dietro le quinte, React esegue alcune operazioni per mantenere il tuo codice ad alte prestazioni e facile da comprendere.

- -

Binding automatico: Quando crei le callback in JavaScript, solitamente devi fare il binding esplicito del metodo alla sua istanza, in modo che il valore di this sia corretto. Con React, ogni metodo è automaticamente legato alla propria istanza del componente (eccetto quando si usa la sintassi delle classi ES6). React immagazzina il metodo legato in maniera tale da essere estremamente efficiente in termini di CPU e memoria. Ti permette anche di scrivere meno codice!

- -

Delega degli eventi: React non associa realmente i gestori di eventi ai nodi stessi. Quando React si avvia, comincia ad ascoltare tutti gli eventi a livello globale usando un singolo event listener. Quando un componente viene montato o smontato, i gestori di eventi sono semplicemente aggiunti o rimossi da un mapping interno. Quando si verifica un evento, React sa come inoltrarlo utilizzando questo mapping. Quando non ci sono più gestori di eventi rimasti nel mapping, i gestori di eventi di React sono semplici operazioni fittizie. Per saperne di più sul perché questo approccio è veloce, leggi l'eccellente articolo sul blog di David Walsh.

-

I Componenti Sono Macchine a Stati Finiti #

-

React considera le UI come semplici macchine a stati finiti. Pensando alla UI come in uno di tanti stati diversi e visualizzando questi stati, è facile mantenere la UI consistente.

- -

In React, aggiorni semplicemente lo stato di un componente, e quindi visualizzi una nuova UI basata su questo nuovo stato. React si occupa di aggiornare il DOM al tuo posto nella maniera più efficiente.

-

Come Funziona lo Stato #

-

Una maniera comune di informare React di un cambiamento nei dati è chiamare setState(data, callback). Questo metodo effettua il merge di data in this.state e ridisegna il componente. Quando il componente ha terminato la fase di ri-rendering, la callback opzionale viene invocata. Nella maggior parte dei casi non avrai bisogno di fornire una callback dal momento che React si occuperà di mantenere la UI aggiornata per te.

-

Quali Componenti Devono Avere uno Stato? #

-

La maggior parte dei tuoi componenti dovrebbero semplicemente ricevere dei dati da props e visualizzarli. Tuttavia, a volte hai bisogno di reagire all'input dell'utente, una richiesta al server o il trascorrere del tempo. In questi casi utilizzi lo stato.

- -

Prova a mantenere il maggior numero possibile dei tuoi componenti privi di stato. Facendo ciò, isolerai lo stato nel suo luogo logicamente corretto e minimizzerai la ridondanza, rendendo più semplice ragionare sulla tua applicazione.

- -

Un pattern comune è quello di creare diversi componenti privi di stato che mostrano semplicemente dati, e di avere un componente dotato di stato al di sopra di essi nella gerarchia, che passa il proprio stato ai suoi figli tramite le props. Il componente dotato di stato incapsula tutta la logica di interazione, mentre i componenti privi di stato si occupano della visualizzazione dei dati in maniera dichiarativa.

-

Cosa Dovrebbe Contenere lo Stato? #

-

Lo stato dovrebbe contenere dati che i gestori di eventi del componente possono modificare per scatenare un aggiornamento della UI. In applicazioni reali, questi dati tendono ad essere molto limitati e serializzabili come JSON. Quando costruisci un componente dotato di stato, pensa alla minima rappresentazione possibile del suo stato, e conserva solo quelle proprietà in this.state. All'interno di render() calcola quindi ogni altra informazione necessaria basandoti sullo stato. Ti accorgerai che pensare e scrivere applicazioni in questo modo porta alla scrittura dell'applicazione più corretta, dal momento che aggiungere valori ridondanti o calcolati allo stato significherebbe doverli mantenere sincronizzati esplicitamente, anziché affidarti a React perché li calcoli al tuo posto.

-

Cosa Non Dovrebbe Contenere lo Stato? #

-

this.state dovrebbe contenere soltanto la quantità minima di dati indispensabile a rappresentare lo stato della tua UI. In quanto tale, non dovrebbe contenere:

- -
    -
  • Dati calcolati: Non preoccuparti di precalcolare valori basati sullo stato — è più semplice assicurarti che la tua UI sia consistente se effettui tutti i calcoli all'interno di render(). Per esempio, se lo stato contiene un array di elementi di una lista, e vuoi mostrare il numero di elementi come stringa, mostra semplicemente this.state.listItems.length + ' elementi nella lista' nel tuo metodo render() anziché conservarlo nello stato.
  • -
  • Componenti React: Costruiscili in render() basandoti sulle proprietà e sullo stato del componente.
  • -
  • Dati duplicati dalle proprietà: Prova ad utilizzare le proprietà come fonte di verità ove possibile. Un uso valido dello stato per i valori delle proprietà è conservarne il valore precedente quando le proprietà cambiano nel tempo.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/interactivity-and-dynamic-uis-ja-JP.html b/docs/interactivity-and-dynamic-uis-ja-JP.html deleted file mode 100644 index ac99882f39..0000000000 --- a/docs/interactivity-and-dynamic-uis-ja-JP.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - 相互作用と動的なUI | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 相互作用と動的なUI -

-
- -

Reactでどうやってデータを表示するかについては既に学んでいます。これからは、どうやって相互に作用するUIを作成するかを見ていきましょう。

-

単純な例 #

var LikeButton = React.createClass({
-  getInitialState: function() {
-    return {liked: false};
-  },
-  handleClick: function(event) {
-    this.setState({liked: !this.state.liked});
-  },
-  render: function() {
-    var text = this.state.liked ? 'liked' : 'haven\'t liked';
-    return (
-      <p onClick={this.handleClick}>
-        You {text} this. Click to toggle.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <LikeButton />,
-  document.getElementById('example')
-);
-

イベントハンドリングとイベントの組み合わせ #

-

Reactでは、普通のHTMLで行っているように単純にキャメルケースのpropとしてイベントハンドラを渡します。ReactはIE8と同じように全てのイベントが動作することと、組み合わされたイベントシステムが実行されることを保証します。これは、Reactが、イベントがどのように発生して、仕様にそってそれをキャプチャする方法を知っていることと、イベントはイベントハンドラに渡されて、どのブラウザを使っていても、W3Cの仕様と一致することを保証することを意味します。

-

中身を見る: オートバインディングとイベントの委譲 #

-

中身を見ていくと、Reactはコードの性能と、理解しやすさを保つためにいくつかのことを行っています。

- -

オートバインディング: JavaScriptでコールバックを作成するときには、普通は this の値が正しくなるように、インスタンスにメソッドをはっきりとバインドする必要があります。 -Reactでは、全てのメソッドが自動でコンポーネントのインスタンスにバインドされます。ReactはCPUとメモリを効率的に使えるように、バインドするメソッドを持っています。これによって、タイピングの量を少なくすることもできます!

- -

イベントの委譲: Reactは実際はノード自体にイベントハンドラをアタッチはしません。Reactを立ち上げる時、1つのイベントリスナを使って最上位で全てのイベントをリスニングし始めます。コンポーネントがマウントされたり、アンマウントされた時は、イベントハンドラは内部のマッピングを単純に加えたり減らしたりします。イベントが起こった時には、Reactはこのマッピングを使ってどのようにディスパッチするかを知っています。マッピングの中にイベントハンドラが無い場合は、Reactのイベントハンドラは何も行いません。なぜこれの速度が速いかについて詳しく知るためには、David Walshの素晴らしいブログの投稿をご覧ください。

-

コンポーネントは静的なマシーンに過ぎない #

-

ReactはUIをただの静的なマシーンと考えます。UIがたくさんのstateの中にあり、それらのstateをレンダリングするものだと考えることで、UIの一貫性を保ちやすくなります。

- -

Reactでは、コンポーネントのstateをアップデートするだけで、新しいstateに基づいた新しいUIをレンダリングします。Reactは最も効率的な方法でDOMをアップデートする面倒を見てくれます。

-

どのようにStateが働くか #

-

Reactがデータの変更を通知する共通な方法は setState(data, callback) を呼ぶことです。このメソッドは datathis.state にマージし、コンポーネントを再度レンダリングします。コンポーネントが再度レンダリングし終わったら、オプションの callback が呼ばれます。ほとんどの場合、 callback を提供する必要はありません。ReactがUIを最新に保ってくれるからです。

-

どのコンポーネントがStateを持っているべきでしょうか? #

-

コンポーネントは単純に props からデータを取得し、レンダリングすべきです。しかし、時々、ユーザのインプットやサーバのリクエストや、時間の経過に反応する必要が有ります。このような場合にstateを使うのです。

- -

コンポーネントの多くを、可能な限りステートレスに保つよう試みてください。 このようにすることで、stateを最もロジックに近い場所から離し、冗長性を減らすことができ、アプリケーションが理解しやすくなります。

- -

共通なパターンはただデータをレンダリングするいくつかのステートレスなコンポーネントを構築することで、 props を通してその子要素にstateを渡す階級でステートフルなコンポーネントを持つことです。ステートフルなコンポーネントは、ステートレスなコンポーネントが叙述的な方法でデータをレンダリングする助けを行う一方で、全ての相互作用のロジックを持ちます。

-

stateで何が行われる べき でしょうか? #

-

stateはUIのアップデートのトリガーとなるコンポーネントのイベントハンドラとしてのデータを保持するべきです。 現実のアプリでは、このデータはとても小さく、JSONでシリアライズできるものになります。ステートフルなコンポーネントを構築する時は、このstateの表現をできるだけ小さくなるように、また、 this.state の中だけにそれらのプロパティを貯めこむように考えてください。 render() の中では、このstateに基づく、他の必要な情報をただ計算してください。このように考えたりアプリケーションを記述したりすることが最も正しいアプリケーションへの道であると発見するでしょう。stateに余剰な値や、計算後の値を加えることはReactがそれらを計算してくれるのに頼るのではなく、同期的にそれらを明白に保つ必要があることを意味します。

-

stateで何が行われる べきではない でしょうか? #

-

this.state UIのstateを表す必要がある最小限の量のデータだけを保持するべきです。このような点で以下のようなものは保持するべきではありません。

- -
    -
  • 計算されたデータ: -stateに基づく事前に計算された値について心配は要りません。 render() を用いて、全ての計算を行って、UIの一貫性を保証するよりも簡単です。例えば、stateにリスト化されたアイテムの配列を持っていて、文字列としてその数をレンダリングしたいとして、それらをstateに保持するよりも render() メソッドに this.state.listItems.length + ' list items' を単純にレンダリングすれば良いのです。
  • -
  • Reactのコンポーネント: 隠れたpropsとstateに基づいて render() でそれらをビルドしてください。
  • -
  • propsからコピーしたデータ: 可能であれば、propsを真のソースとして使ってみてください。propsは時とともに変化し得るので、正しくstateにpropsを保持する使い方は、以前の値を知っていることになり得ます。
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/interactivity-and-dynamic-uis-ko-KR.html b/docs/interactivity-and-dynamic-uis-ko-KR.html deleted file mode 100644 index 368ec4f5df..0000000000 --- a/docs/interactivity-and-dynamic-uis-ko-KR.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - 상호 작용 및 동적 UI | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 상호 작용 및 동적 UI -

-
- -

이미 React에서 어떻게 데이터를 표시하는지를 배웠습니다. 이제 UI와의 상호작용을 어떻게 만드는지 살펴보죠.

-

간단한 예제 #

var LikeButton = React.createClass({
-  getInitialState: function() {
-    return {liked: false};
-  },
-  handleClick: function(event) {
-    this.setState({liked: !this.state.liked});
-  },
-  render: function() {
-    var text = this.state.liked ? 'liked' : 'haven\'t liked';
-    return (
-      <p onClick={this.handleClick}>
-        You {text} this. Click to toggle.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <LikeButton />,
-  document.getElementById('example')
-);
-

이벤트 핸들링과 통합적인(Synthetic) 이벤트 #

-

React에서의 이벤트 핸들러는 HTML에서 그러던 것처럼 간단히 카멜케이스 프로퍼티(camelCased prop)로 넘기면 됩니다. React의 모든 이벤트는 통합적인 이벤트 시스템의 구현으로 IE8 이상에서는 같은 행동이 보장됩니다. 즉, React는 사양에 따라 어떻게 이벤트를 일으키고(bubble) 잡는지 알고 있고, 당신이 사용하는 브라우저와 관계없이 이벤트 핸들러에 전달되는 이벤트는 W3C 사양과 같도록 보장됩니다.

-

기본 구현: 오토바인딩과 이벤트 델리게이션 #

-

- -

코드를 고성능으로 유지하고 이해하기 쉽게 하기 위해, React는 보이지 않는 곳에서 몇 가지 일을 수행합니다.

- -

오토바인딩: JavaScript에서 콜백을 만들 때, 보통은 this의 값이 정확하도록 명시적으로 메소드를 인스턴스에 바인드해야 합니다. React에서는 모든 메소드가 자동으로 React의 컴포넌트 인스턴스에 바인드됩니다.(ES6 클래스 문법을 사용할 때는 재외하고) React가 바인드 메소드를 캐시하기 때문에 매우 CPU와 메모리에 효율적입니다. 타이핑해야 할 것도 줄어들죠!

- -

이벤트 델리게이션: React는 실제로는 노드자신에게 이벤트 핸들러를 붙이지 않습니다. React가 시작되면 React는 탑 레벨의 단일 이벤트 리스너로 모든 이벤트를 리스닝하기 시작합니다. 컴포넌트가 마운트되거나 언마운트 될 때, 이벤트 핸들러는 그냥 내부 매핑에서 넣거나 뺄 뿐입니다. 이벤트가 발생하면, React는 이 매핑을 사용해서 어떻게 디스패치할 지를 알게 됩니다. 매핑에 이벤트 핸들러가 남아있지 않으면, React의 이벤트 핸들러는 그냥 아무것도 하지 않습니다. 왜 이 방식이 빠른지 더 알고 싶으시면, David Walsh의 멋진 블로그 글을 읽어 보세요.

-

컴포넌트는 그냥 state 머신일 뿐 #

-

React는 UI를 간단한 state 머신이라 생각합니다. UI를 다양한 state와 그 state의 렌더링으로 생각함으로써 UI를 일관성 있게 관리하기 쉬워집니다.

- -

React에서는, 간단히 컴포넌트의 state를 업데이트하고, 이 새로운 state의 UI를 렌더링합니다. React는 DOM의 변경을 가장 효율적인 방법으로 관리해줍니다.

-

state의 동작 원리 #

-

React에게 데이터의 변경을 알리는 일반적인 방법은 setState(data, callback)을 호출하는 것입니다. 이 메소드는 this.statedata를 머지하고 컴포넌트를 다시 렌더링 합니다. 컴포넌트의 재-렌더링이 끝나면, 생략가능한 callback이 호출됩니다. 대부분의 경우 React가 UI를 최신상태로 유지해주기 때문에 callback을 사용할 필요가 없습니다.

-

어떤 컴포넌트가 state를 가져야 할까요? #

-

대부분의 컴포넌트는 props로부터 데이터를 받아 렌더할 뿐입니다만, 가끔 유저 인풋, 서버 요청, 시간의 경과에 반응해야 할 필요가 있습니다. 이럴 때 state를 사용합니다.

- -

가능한 한 컴포넌트가 상태를 가지지 않도록(stateless) 하세요. 이렇게 함으로써 가장 논리적인 장소로 state를 격리하게 되고 쉽게 애플리케이션을 추론할 수 있도록 중복을 최소화할 수 있습니다.

- -

일반적인 패턴은 데이터만 렌더하는 여러 상태를 가지지 않은 컴포넌트를 만들고, 그 위에 상태기반(stateful) 컴포넌트를 만들어 계층 안의 자식 컴포넌트에게 props를 통해 state를 전달하는 것입니다. state를 가지지 않은 컴포넌트가 선언적인 방법으로 데이터를 렌더링 하는 동안, 상태기반 컴포넌트는 모든 상호작용 로직을 캡슐화합니다.

-

state를 어떻게 써야 할까요? #

-

state는 컴포넌트의 이벤트 핸들러에 의해 UI 업데이트를 트리거할때 변경될 가능성이 있어, 그때 사용할 데이터를 가져야 합니다. 실제 앱에서는 이 데이터는 매우 작고 JSON 직렬화 가능한 경향이 있습니다. 상태기반 컴포넌트를 만들때, 가능한 작게 state를 서술하고 this.state에만 저장하도록 해보세요. 그냥 render() 안에서 이 state를 기반으로 다른 모든 정보를 계산합니다. 이 방식으로 애플리케이션을 작성하고 생각하면 가장 최적의 애플리케이션으로 발전해가는 경향이 있다는 것을 발견하게 될 것입니다. 꼭 필요하지 않은 값이나 계산된 값을 state에 추가하는 것은 render가 그것을 계산하는 대신에 명시적으로 그것들을 맞춰줘야 하는 것을 의미하기 때문이죠.

-

state를 어떻게 쓰지 말아야 할까요? #

-

this.state는 UI의 state를 표현할 최소한의 데이터만을 가져야 합니다. 그래서 이런 것들을 가지지 않게끔 해야 합니다.

- -
    -
  • 계산된 데이터: state에 따라 값을 미리 계산하는 것에 대해 염려하지 마세요. 계산은 모두 render()에서 하는 것이 UI의 일관성을 유지하기 쉽습니다. 예를 들어, state에서 list items 배열을 가지고 있고 문자열으로 카운트를 렌더링 할 경우, state에 저장하기보다는 그냥 render() 메소드안에서 this.state.listItems.length + ' list items'를 렌더하세요.
  • -
  • React 컴포넌트: 가지고 있는 props와 state로 render()안에서 만드세요.
  • -
  • props에서 복사한 데이터: 가능한 한 원래의 소스로 props를 사용하도록 해보세요. props를 state에 저장하는 단 하나의 올바른 사용법은 이전 값을 알고 싶을 때입니다. props는 부모 컴포넌트의 재 렌더링의 결과 변경될 수도 있기 때문이죠.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/interactivity-and-dynamic-uis-ru-RU.html b/docs/interactivity-and-dynamic-uis-ru-RU.html deleted file mode 100644 index 949b1ba465..0000000000 --- a/docs/interactivity-and-dynamic-uis-ru-RU.html +++ /dev/null @@ -1,551 +0,0 @@ - - - - - - - Интерактивные и динамические интерфейсы | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Интерактивные и динамические интерфейсы -

-
- -

Вы уже знаете как показывать данные с React. Теперь давайте добавим в наши интферфейсы немного интерактивности.

-

Простой пример #

var LikeButton = React.createClass({
-  getInitialState: function() {
-    return {liked: false};
-  },
-  handleClick: function(event) {
-    this.setState({liked: !this.state.liked});
-  },
-  render: function() {
-    var text = this.state.liked ? 'liked' : 'haven\'t liked';
-    return (
-      <p onClick={this.handleClick}>
-        You {text} this. Click to toggle.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <LikeButton />,
-  document.getElementById('example')
-);
-

Обработка событий и синтетические события #

-

С React вы просто передаете функцию-обработчик нужного события как аргумент, почти так же, как делали это в HTML. Благодаря механизму синтетических событий React гарантирует, что все события будут вести себя одинаково во всех браузерах. Другими словами, React знает, как работает всплытие и перехват событий по спецификации. События, которые он передает в ваши обработчики, будут соответствовать спецификации W3C, несмотря на то, каким браузером вы пользуетесь.

-

Как это работает: автоматическое связывание и делегирование событий #

-

Чтобы ваш код был не только понятным, но и быстрым, React делает следующее:

- -

Автоматическое связывание: Когда в JavaScript создаются функции обратного вызова, вам надо привязать метод к тому объекту, на котором он будет вызываться, чтобы значение this было корректным. С React привязка метода к компоненту происходит автоматически (кроме тех случаев, когда вы используете классы ES6). И делается это с минимальной нагрузкой на процессор и память.

- -

Делегирование событий: На самом же деле, React добавляет обработчики событий не к узлам дерева. Сразу после запуска, React начинает прослушивать все события с самого верхнего уровня, используя единый слушатель. Когда добавляется новый компонент или удаляется старый, обработчики событий просто добавляются или удаляются из памяти React. И когда событие наступает, React уже заранее знает какому из обработчиков его передать. Когда в памяти больше не остается обработчиков, React перестает обрабатывать события. Если хотите узнать о том, почему эта механика так быстро работает, почитайте отличный пост в блоге David Walsh.

-

Компоненты как конечные автоматы #

-

React считает интерфейсы обыкновенными конечными автоматами. Работать с интерфейсом становится проще, если представлять его как конечный автомат, который меняет состояния и отрисовывает их.

- -

В React вы просто обновляете состояние компонента, а потом выводите новый интерфейс уже с новыми данными. Все изменения в DOM-дереве React сделает сам, причем наиболее эффективным способом.

-

Как работает состояние #

-

Чтобы сообщить React о том, что данные изменились, вы вызываете метод setState(data, callback). В этом методе происходит обновление состояния this.state новыми данными из data, и компонент отрисуется заново. После этого вызывается функция callback. Но вы редко будете ей пользоваться, ведь React сам обновляет интерфейс.

-

В каких компонентах хранить состояние? #

-

Большинство компонентов должны просто брать данные из props и отрисовывать их. Но иногда вам надо реагировать на действия пользователя, делать запросы на сервер или просто сделать что-то по таймеру. В таких случаях используйте состояние.

- -

Старайтесь делать компоненты без состояния. Следуя этому правилу, вы будете выносить работу с состоянием с уровня представления в другие, более подходящие места. Тем самым, вы снизите сложность приложения, упрощая его понимание.

- -

Основной принцип такой: создаются несколько компонентов без состояния, которые формируют дерево. Они будут заниматься только отрисовкой данных. А все данные для них будут у родительского компонента, который будет на вершине этого дерева компонентов. Он и будет передавать данные дочерним узлам через props. Этот компонент с общим состоянием содержит в себе всю логику взаимодействия, а дочерние компоненты будут только отрисовывать данные, которые будут у них в props.

-

Какие данные надо помещать в состояние? #

-

Состояние должно содержать данные, которые нужны для обновления интерфейса. В реальных приложениях такие данные, как правило, незначительны по объему, и могут быть сериализованы в JSON. Когда вы создаете компонент с состоянием, старайтесь поместить в него минимум данных. А уже внутри метода render() вычисляйте остальные данные, используя значения из состояния. -Со временем вы увидите, что такой подход позволяет создавать более стройные и устойчивые к изменениям приложения. Добавление в состояние лишних данных требует от вас дополнительных затрат на их синхронизацию. Но этого можно избежать, если позволить React делать все эти вычисления за вас.

-

Какие данные не надо помещать в состояние? #

-

Состояние this.state должно содержать минимум данных, необходимых для отображения интерфейса. Поэтому не стоит хранить в нем:

- -
    -
  • Вычисляемые данные: Не волнуйтесь о данных, которые можно вычислить из состояния. Согласованность данных проще обеспечить, если производить все вычисления в методе render(). Например, если в состоянии хранится список элементов, и вам надо вывести его размер в виде строки, напишите this.state.listItems.length + ' элементов' в методе render(). Это будет правильнее, чем хранить размер списка в состоянии.
  • -
  • Компоненты React: Создавайте их в методе render(), опираясь на данные из props и state.
  • -
  • Значения, повторяющие props: Старайтесь по мере возможности использовать props как единственный источник данных. Хранить значения props в состоянии допускается, только если вам надо где-то хранить их прошлые значения, ведь props могут измениться после отрисовки родительского компонента.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/interactivity-and-dynamic-uis-zh-CN.html b/docs/interactivity-and-dynamic-uis-zh-CN.html deleted file mode 100644 index 8ecc610f31..0000000000 --- a/docs/interactivity-and-dynamic-uis-zh-CN.html +++ /dev/null @@ -1,550 +0,0 @@ - - - - - - - 动态交互式用户界面 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 动态交互式用户界面 -

-
- -

我们已经学习如何使用 React 显示数据。现在让我们来学习如何创建交互式界面。

-

简单例子 #

var LikeButton = React.createClass({
-  getInitialState: function() {
-    return {liked: false};
-  },
-  handleClick: function(event) {
-    this.setState({liked: !this.state.liked});
-  },
-  render: function() {
-    var text = this.state.liked ? 'liked' : 'haven\'t liked';
-    return (
-      <p onClick={this.handleClick}>
-        You {text} this. Click to toggle.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <LikeButton />,
-  document.getElementById('example')
-);
-

事件处理与合成事件(Synthetic Events) #

-

React 里只需把事件处理器(event handler)以骆峰命名(camelCased)形式当作组件的 props 传入即可,就像使用普通 HTML 那样。React 内部创建一套合成事件系统来使所有事件在 IE8 和以上浏览器表现一致。也就是说,React 知道如何冒泡和捕获事件,而且你的事件处理器接收到的 events 参数与 W3C 规范 一致,无论你使用哪种浏览器。

-

幕后原理:自动绑定(Autobinding)和事件代理(Event Delegation) #

-

在幕后,React 做了一些操作来让代码高效运行且易于理解。

- -

自动绑定: 在 JavaScript 里创建回调的时候,为了保证 this 的正确性,一般都需要显式地绑定方法到它的实例上。在 React 中,所有方法被自动绑定到了它的组件实例上(除非使用ES6的class符号)。React 还缓存这些绑定方法,所以 CPU 和内存都是非常高效。而且还能减少打字!

- -

事件代理: React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里没有事件处理函数时,会当作空操作处理。参考 David Walsh 很棒的文章 了解这样做高效的原因。

-

组件其实是状态机(State Machines) #

-

React 把用户界面当作简单状态机。把用户界面想像成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。

- -

React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。

-

State 工作原理 #

-

常用的通知 React 数据变化的方法是调用 setState(data, callback)。这个方法会合并(merge) datathis.state,并重新渲染组件。重新渲染完成后,调用可选的 callback 回调。大部分情况下不需要提供 callback,因为 React 会负责把界面更新到最新状态。

-

哪些组件应该有 State? #

-

大部分组件的工作应该是从 props 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。

- -

尝试把尽可能多的组件无状态化。 这样做能隔离 state,把它放到最合理的地方,也能减少冗余,同时易于解释程序运作过程。

- -

常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 props 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。

-

哪些 应该 作为 State? #

-

State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,思考一下表示它的状态最少需要哪些数据,并只把这些数据存入 this.state。在 render() 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,那么你就需要经常手动保持数据同步,而不能让 React 来帮你处理。

-

哪些 不应该 作为 State? #

-

this.state 应该仅包括能表示用户界面状态所需的最少数据。因此,它不应该包括:

- -
    -
  • 计算所得数据: 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到 render() 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 render() 里使用 this.state.listItems.length + ' list items' 比把它放到 state 里好的多。
  • -
  • React 组件:render() 里使用当前 props 和 state 来创建它。
  • -
  • 基于 props 的重复数据: 尽可能使用 props 来作为实际状态的源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为 props 可能因为父组件的重绘而变化。
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/interactivity-and-dynamic-uis.html b/docs/interactivity-and-dynamic-uis.html index fcd80ba69d..778b64784c 100644 --- a/docs/interactivity-and-dynamic-uis.html +++ b/docs/interactivity-and-dynamic-uis.html @@ -1,554 +1,10 @@ - - - - - - Interactivity and Dynamic UIs | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Interactivity and Dynamic UIs -

-
- -

You've already learned how to display data with React. Now let's look at how to make our UIs interactive.

-

A Simple Example #

class LikeButton extends React.Component {
-  constructor() {
-    super();
-    this.state = {
-      liked: false
-    };
-    this.handleClick = this.handleClick.bind(this);
-  }
-  handleClick() {
-    this.setState({liked: !this.state.liked});
-  }
-  render() {
-    const text = this.state.liked ? 'liked' : 'haven\'t liked';
-    return (
-      <div onClick={this.handleClick}>
-        You {text} this. Click to toggle.
-      </div>
-    );
-  }
-}
-
-ReactDOM.render(
-  <LikeButton />,
-  document.getElementById('example')
-);
-

Event Handling and Synthetic Events #

-

With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave similarly in all browsers by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with the W3C spec, regardless of which browser you're using.

-

Under the Hood: Autobinding and Event Delegation #

-

Under the hood, React does a few things to keep your code performant and easy to understand.

- -

Autobinding: When creating callbacks in JavaScript, you usually need to explicitly bind a method to its instance such that the value of this is correct. With React, every method is automatically bound to its component instance (except when using ES6 class syntax). React caches the bound method such that it's extremely CPU and memory efficient. It's also less typing!

- -

Event delegation: React doesn't actually attach event handlers to the nodes themselves. When React starts up, it starts listening for all events at the top level using a single event listener. When a component is mounted or unmounted, the event handlers are simply added or removed from an internal mapping. When an event occurs, React knows how to dispatch it using this mapping. When there are no event handlers left in the mapping, React's event handlers are simple no-ops. To learn more about why this is fast, see David Walsh's excellent blog post.

-

Components are Just State Machines #

-

React thinks of UIs as simple state machines. By thinking of a UI as being in various states and rendering those states, it's easy to keep your UI consistent.

- -

In React, you simply update a component's state, and then render a new UI based on this new state. React takes care of updating the DOM for you in the most efficient way.

-

How State Works #

-

A common way to inform React of a data change is by calling setState(data, callback). This method merges data into this.state and re-renders the component. When the component finishes re-rendering, the optional callback is called. Most of the time you'll never need to provide a callback since React will take care of keeping your UI up-to-date for you.

-

What Components Should Have State? #

-

Most of your components should simply take some data from props and render it. However, sometimes you need to respond to user input, a server request or the passage of time. For this you use state.

- -

Try to keep as many of your components as possible stateless. By doing this you'll isolate the state to its most logical place and minimize redundancy, making it easier to reason about your application.

- -

A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via props. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.

-

What Should Go in State? #

-

State should contain data that a component's event handlers may change to trigger a UI update. In real apps this data tends to be very small and JSON-serializable. When building a stateful component, think about the minimal possible representation of its state, and only store those properties in this.state. Inside of render() simply compute any other information you need based on this state. You'll find that thinking about and writing applications in this way tends to lead to the most correct application, since adding redundant or computed values to state means that you need to explicitly keep them in sync rather than rely on React computing them for you.

-

What Shouldn't Go in State? #

-

this.state should only contain the minimal amount of data needed to represent your UI's state. As such, it should not contain:

- -
    -
  • Computed data: Don't worry about precomputing values based on state — it's easier to ensure that your UI is consistent if you do all computation within render(). For example, if you have an array of list items in state and you want to render the count as a string, simply render this.state.listItems.length + ' list items' in your render() method rather than storing it on state.
  • -
  • React components: Build them in render() based on underlying props and state.
  • -
  • Duplicated data from props: Try to use props as the source of truth where possible. One valid use to store props in state is to be able to know its previous values, because props may change as the result of a parent component re-rendering.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/introducing-jsx.html b/docs/introducing-jsx.html new file mode 100644 index 0000000000..7014b3240a --- /dev/null +++ b/docs/introducing-jsx.html @@ -0,0 +1,515 @@ + + + + + + + + + Introducing JSX - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Introducing JSX +

+
+ +

Consider this variable declaration:

+
const element = <h1>Hello, world!</h1>;
+
+

This funny tag syntax is neither a string nor HTML.

+ +

It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript.

+ +

JSX produces React "elements". We will explore rendering them to the DOM in the next section. Below, you can find the basics of JSX necessary to get you started.

+

Embedding Expressions in JSX #

+

You can embed any JavaScript expression in JSX by wrapping it in curly braces.

+ +

For example, 2 + 2, user.name, and formatName(user) are all valid expressions:

+
function formatName(user) {
+  return user.firstName + ' ' + user.lastName;
+}
+
+const user = {
+  firstName: 'Harper',
+  lastName: 'Perez'
+};
+
+const element = (
+  <h1>
+    Hello, {formatName(user)}!
+  </h1>
+);
+
+ReactDOM.render(
+  element,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

We wrapped JSX in parentheses and split it over multiple lines for readability. This also helps avoid the pitfalls of automatic semicolon insertion.

+

JSX is an Expression Too #

+

After compilation, JSX expressions become regular JavaScript objects.

+ +

This means that you can use JSX inside of if statements and for loops, assign it to variables, accept it as arguments, and return it from functions:

+
function getGreeting(user) {
+  if (user) {
+    return <h1>Hello, {formatName(user.name)}!</h1>;
+  } else {
+    return <h1>Hello, Stranger.</h1>;
+  }
+}
+

Specifying Attributes with JSX #

+

You may use quotes to specify string literals as attributes:

+
const element = <div tabIndex="0"></div>;
+
+

You may also use curly braces to embed a JavaScript expression in an attribute:

+
const element = <img src={user.avatarUrl}></img>;
+

Specifying Children with JSX #

+

If a tag is empty, you may close it immediately with />, like XML:

+
const element = <img src={user.avatarUrl} />;
+
+

JSX tags may contain children:

+
const element = (
+  <div>
+    <h1>Hello!</h1>
+    <h2>Good to see you here.</h2>
+  </div>
+);
+
+
+

Caveat:

+ +

Since JSX is closer to JavaScript than HTML, React DOM uses camelCase property naming convention instead of HTML attribute names.

+ +

For example, class becomes className in JSX, and tabindex becomes tabIndex.

+
+

JSX Prevents Injection Attacks #

+

It is safe to embed user input in JSX:

+
const title = response.potentiallyMaliciousInput;
+// This is safe:
+const element = <h1>{title}</h1>;
+
+

By default, React DOM escapes any values embedded in JSX before rendering them.

+

JSX Represents Objects #

+

Babel compiles JSX down to React.createElement() calls.

+ +

These two examples are identical:

+
const element = (
+  <h1 className="greeting">
+    Hello, world!
+  </h1>
+);
+
const element = React.createElement(
+  'h1',
+  {className: 'greeting'},
+  'Hello, world!'
+);
+
+

React.createElement() performs a few checks to help you write bug-free code but essentially it creates an object like this:

+
// Note: this structure is simplified
+const element = {
+  type: 'h1',
+  props: {
+    className: 'greeting',
+    children: 'Hello, world'
+  }
+};
+
+

These objects are called "React elements". You can think of them as descriptions of what you want to see on the screen. React reads these objects and uses them to construct the DOM and keep it up to date.

+ +

We will explore rendering React elements to the DOM in the next section.

+ +
+

Tip:

+ +

We recommend searching for a "Babel" syntax scheme for your editor of choice so that both ES6 and JSX code is properly highlighted.

+
+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/jsx-gotchas-it-IT.html b/docs/jsx-gotchas-it-IT.html deleted file mode 100644 index ddf6478e2f..0000000000 --- a/docs/jsx-gotchas-it-IT.html +++ /dev/null @@ -1,531 +0,0 @@ - - - - - - - JSX Gotchas | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX Gotchas -

-
- -

JSX somiglia all'HTML ma ci sono delle differenze importanti da tenere in considerazione.

- -
-

Nota:

- -

Per le differenze del DOM, come l'attributo style in linea, consulta here.

-
-

Entità HTML #

-

Puoi inserire entità HTML nel testo letterale in JSX:

-
<div>Primo &middot; Secondo</div>
-
-

Se desideri visualizzare un'entità HTML all'interno di un contenuto dinamico, avrai problemi con il doppio escape, poiché React effettua in maniera predefinita l'escape di tutte le stringhe visualizzate per prevenire un'ampia gamma di attacchi XSS.

-
// Male: Mostra "Primo &middot; Secondo"
-<div>{'Primo &middot; Secondo'}</div>
-
-

Esistono molte maniere di aggirare questo problema. La più facile è scrivere i caratteri Unicode direttamente in JavaScript. Dovrai assicurarti che il file sia salvato come UTF-8 e che le appropriate direttive UTF-8 siano impostate in modo che il browser li visualizzi correttamente.

-
<div>{'Primo · Secondo'}</div>
-
-

Un'alternativa più sicura consiste nel trovare il codice Unicode corrispondente all'entità e usarlo all'interno di una stringa JavaScript.

-
<div>{'Primo \u00b7 Secondo'}</div>
-<div>{'Primo ' + String.fromCharCode(183) + ' Secondo'}</div>
-
-

Puoi usare array misti con stringhe ed elementi JSX.

-
<div>{['Primo ', <span>&middot;</span>, ' Secondo']}</div>
-
-

Come ultima risorsa, puoi sempre inserire HTML nativo.

-
<div dangerouslySetInnerHTML={{__html: 'Primo &middot; Secondo'}} />
-

Attributi HTML Personalizzati #

-

Se passi proprietà che non esistono nella specifica HTML ad elementi HTML nativi, React li ignorerà. Se vuoi usare un attributo personalizzato, devi prefiggerlo con data-.

-
<div data-custom-attribute="foo" />
-
-

Gli attributi per l'Accessibilità del Web che iniziano per aria- saranno gestiti correttamente.

-
<div aria-hidden={true} />
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-gotchas-ja-JP.html b/docs/jsx-gotchas-ja-JP.html deleted file mode 100644 index 019a018077..0000000000 --- a/docs/jsx-gotchas-ja-JP.html +++ /dev/null @@ -1,530 +0,0 @@ - - - - - - - JSXの理解 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSXの理解 -

-
- -

JSXはHTMLに似ていますが、重要な違いがいくつかあります。

- -
-

注意: -インラインの style 属性のようなDOMの違いについては、こちらを確認してください。

-
-

HTMLのエンティティ #

-

以下のように、JSXの文字のテキストの中にHTMLのエンティティを挿入することができます。

-
<div>First &middot; Second</div>
-
-

動的なコンテンツとしてHTMLのエンティティを表示する際に、ダブルエスケープを書いてしまうことがあるかと思いますが、Reactはデフォルトで広い範囲のXSS攻撃を防ぐために表示しようとしている全ての文字列をエスケープします。

-
// 悪い例: 以下は "First &middot; Second" を表示します。
-<div>{'First &middot; Second'}</div>
-
-

この問題を防止するためにはいくつかの方法があります。最も簡単な方法は、unicodeの文字を直でJavaScriptに記述する方法です。その際には、ファイルがUTF-8で保存されていることと、ブラウザが正しく表示できるように、UTF-8で表示する命令が正しくセットされていることを確認してください。

-
<div>{'First · Second'}</div>
-
-

さらに安全な代替の方法は、エンティティに対応するunicodeの数値を見つけて、JavaScriptの文字列の中でそれを使うことです。

-
<div>{'First \u00b7 Second'}</div>
-<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
-
-

配列と文字列とJSXの要素を混ぜて使うこともできます。

-
<div>{['First ', <span>&middot;</span>, ' Second']}</div>
-
-

最後の手段として、常に生のHTMLを挿入することもできます。

-
<div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />
-

カスタムされたHTMLの属性 #

-

HTMLの仕様書に存在しない要素をネイティブなHTML要素に渡した場合は、Reactはそれらをレンダリングしません。カスタムした属性を使う場合は、 data- を頭につけてください。

-
<div data-custom-attribute="foo" />
-
-

aria- から始まるWebアクセシビリティ属性はプロパティをレンダリングします。

-
<div aria-hidden={true} />
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-gotchas-ko-KR.html b/docs/jsx-gotchas-ko-KR.html deleted file mode 100644 index 0f2902fdab..0000000000 --- a/docs/jsx-gotchas-ko-KR.html +++ /dev/null @@ -1,531 +0,0 @@ - - - - - - - JSX Gotchas | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX Gotchas -

-
- -

JSX는 HTML처럼 보이지만, 작업하다 보면 마주치게 될 몇 가지 중요한 차이점이 있습니다.

- -
-

주의:

- -

인라인 style 어트리뷰트 같은 DOM과의 차이점은 여기를 보세요.

-
-

HTML 엔티티 #

-

JSX의 리터럴 텍스트에 HTML 엔티티를 넣을 수 있습니다.

-
<div>First &middot; Second</div>
-
-

동적 콘텐츠 안에 HTML 엔티티를 표시하려 할 때, React에서는 XSS 공격을 광범위하게 막기 위해서 기본적으로 모든 표시하는 문자열을 이스케이프 하기 때문에 더블 이스케이프 문제에 부딪히게 됩니다.

-
// 나쁨: "First &middot; Second"를 표시
-<div>{'First &middot; Second'}</div>
-
-

이 이슈를 피해 갈 방법은 여럿 있지만, 가장 쉬운 방법은 유니코드 문자를 JavaScript에 직접 쓰는 것입니다. 브라우저가 올바르게 표시하도록 파일이 UTF-8으로 저장되어 있고 올바른 UTF-8 지시자를 사용하고 있는지 확인해야 합니다.

-
<div>{'First · Second'}</div>
-
-

더 안전한 대안으로 엔티티에 대응하는 유니코드 숫자를 찾아 JavaScript 문자열 안에서 사용하는 방법도 있습니다.

-
<div>{'First \u00b7 Second'}</div>
-<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
-
-

문자열과 JSX 엘리먼트를 혼합한 배열을 사용할 수도 있습니다.

-
<div>{['First ', <span>&middot;</span>, ' Second']}</div>
-
-

최후의 수단으로, 항상 생 HTML을 삽입할 수 있습니다.

-
<div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />
-

커스텀 HTML 어트리뷰트 #

-

프로퍼티를 HTML 사양에는 없는 네이티브 HTML 엘리먼트에 넘기면, React는 그 프로퍼티를 렌더하지 않습니다. 커스텀 어트리뷰트를 사용하고 싶다면, 접두사로 data-를 붙이셔야 합니다.

-
<div data-custom-attribute="foo" />
-
-

aria-로 시작하는 Web 접근성 어트리뷰트는 제대로 렌더될 것입니다.

-
<div aria-hidden={true} />
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-gotchas-zh-CN.html b/docs/jsx-gotchas-zh-CN.html deleted file mode 100644 index 0bf968a319..0000000000 --- a/docs/jsx-gotchas-zh-CN.html +++ /dev/null @@ -1,534 +0,0 @@ - - - - - - - JSX 陷阱 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX 陷阱 -

-
- -

JSX 与 HTML 非常相似,但是有些关键区别要注意。

- -
-

注意:

- -

关于 DOM 的区别,如行内样式属性 style,参考 DOM 区别

-
-

HTML 实体 #

-

HTML 实体可以插入到 JSX 的文本中。

-
<div>First &middot; Second</div>
-
-

如果想在 JSX 表达式中显示 HTML 实体,可以会遇到二次转义的问题,因为 React 默认会转义所有字符串,为了防止各种 XSS 攻击。

-
// 错误: 会显示 “First &middot; Second”
-<div>{'First &middot; Second'}</div>
-
-

有多种绕过的方法。最简单的是直接用 Unicode 字符。这时要确保文件是 UTF-8 编码且网页也指定为 UTF-8 编码。

-
<div>{'First · Second'}</div>
-
-

安全的做法是先找到 实体的 Unicode 编号 ,然后在 JavaScript 字符串里使用。

-
<div>{'First \u00b7 Second'}</div>
-<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
-
-

可以在数组里混合使用字符串和 JSX 元素。

-
<div>{['First ', <span>&middot;</span>, ' Second']}</div>
-
-

万不得已,可以直接插入原始HTML

-
<div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />
-

自定义 HTML 属性 #

-

如果往原生 HTML 元素里传入 HTML 规范里不存在的属性,React 不会显示它们。如果需要使用自定义属性,要加 data- 前缀。

-
<div data-custom-attribute="foo" />
-
-

然而,在自定义元素中任意的属性都是被支持的 (那些在tag名里带有连接符或者 is="..." 属性的)

-
<x-my-component custom-attribute="foo" />
-
-

aria- 开头的 网络无障碍 属性可以正常使用。

-
<div aria-hidden={true} />
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-gotchas.html b/docs/jsx-gotchas.html deleted file mode 100644 index e6e5dc1f9d..0000000000 --- a/docs/jsx-gotchas.html +++ /dev/null @@ -1,534 +0,0 @@ - - - - - - - JSX Gotchas | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX Gotchas -

-
- -

JSX looks like HTML but there are some important differences you may run into.

- -
-

Note:

- -

For DOM differences, such as the inline style attribute, check here.

-
-

HTML Entities #

-

You can insert HTML entities within literal text in JSX:

-
<div>First &middot; Second</div>
-
-

If you want to display an HTML entity within dynamic content, you will run into double escaping issues as React escapes all the strings you are displaying in order to prevent a wide range of XSS attacks by default.

-
// Bad: It displays "First &middot; Second"
-<div>{'First &middot; Second'}</div>
-
-

There are various ways to work-around this issue. The easiest one is to write Unicode characters directly in JavaScript. You need to make sure that the file is saved as UTF-8 and that the proper UTF-8 directives are set so the browser will display it correctly.

-
<div>{'First · Second'}</div>
-
-

A safer alternative is to find the unicode number corresponding to the entity and use it inside of a JavaScript string.

-
<div>{'First \u00b7 Second'}</div>
-<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
-
-

You can use mixed arrays with strings and JSX elements. Each JSX element in the array needs a unique key.

-
<div>{['First ', <span key="middot">&middot;</span>, ' Second']}</div>
-
-

As a last resort, you always have the ability to insert raw HTML.

-
<div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />
-

Custom HTML Attributes #

-

If you pass properties to native HTML elements that do not exist in the HTML specification, React will not render them. If you want to use a custom attribute, you should prefix it with data-.

-
<div data-custom-attribute="foo" />
-
-

However, arbitrary attributes are supported on custom elements (those with a hyphen in the tag name or an is="..." attribute).

-
<x-my-component custom-attribute="foo" />
-
-

Web Accessibility attributes starting with aria- will be rendered properly.

-
<div aria-hidden={true} />
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-in-depth-it-IT.html b/docs/jsx-in-depth-it-IT.html deleted file mode 100644 index f588472ed8..0000000000 --- a/docs/jsx-in-depth-it-IT.html +++ /dev/null @@ -1,669 +0,0 @@ - - - - - - - JSX in Profondità | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX in Profondità -

-
- -

JSX è un'estensione della sintassi JavaScript che somiglia all'XML. Puoi usare una semplice trasformazione sintattica di JSX con React.

-

Perché JSX? #

-

Non devi per forza utilizzare JSX con React. Puoi anche usare semplice JS. Tuttavia, raccomandiamo di utilizzare JSX perché usa una sintassi concisa e familiare per definire strutture ad albero dotate di attributi.

- -

È più familiare a sviluppatori occasionali come i designer.

- -

L'XML ha i benefici di tag di apertura e chiusura bilanciati. Ciò rende la lettura di grandi strutture ad albero più semplice di chiamate a funzione o oggetti letterali.

- -

Non altera la semantica di JavaScript.

-

Tag HTML o Componenti React #

-

React può sia rendere tag HTML (stringhe) che componenti React (classi).

- -

Per rendere untag HTML, usa nomi di tag minuscoli in JSX:

-
var myDivElement = <div className="foo" />;
-ReactDOM.render(myDivElement, document.getElementById('example'));
-
-

Per rendere un componente React, definisci una variabile locale che comincia con una lettera maiuscola:

-
var MyComponent = React.createClass({/*...*/});
-var myElement = <MyComponent someProperty={true} />;
-ReactDOM.render(myElement, document.getElementById('example'));
-
-

Il JSX di React utilizza la convenzione maiuscolo o minuscolo per distinguere tra classi di componenti locali e tag HTML.

- -
-

Nota:

- -

Poiché JSX è JavaScript, gli identificatori come class e for sono sconsigliati -come nomi di attributi XML. Invece, i componenti DOM React si aspettano nomi di proprietà -come className e htmlFor rispettivamente.

-
-

La Trasformazione #

-

Il JSX di React viene trasformato da una sintassi XML a JavaScript nativo. Gli elementi XML, gli attributi e i figli sono trasformati in argomenti passati a React.createElement.

-
var Nav;
-// Input (JSX):
-var app = <Nav color="blue" />;
-// Output (JS):
-var app = React.createElement(Nav, {color:"blue"});
-
-

Osserva che per utilizzare <Nav />, la variabile Nav deve essere visibile.

- -

JSX permette anche di specificare i figli usando una sintassi XML:

-
var Nav, Profile;
-// Input (JSX):
-var app = <Nav color="blue"><Profile>click</Profile></Nav>;
-// Output (JS):
-var app = React.createElement(
-  Nav,
-  {color:"blue"},
-  React.createElement(Profile, null, "click")
-);
-
-

JSX inferirà il displayName della classe dall'assegnazione delle variabile, quando il valore di displayName è indefinito:

-
// Input (JSX):
-var Nav = React.createClass({ });
-// Output (JS):
-var Nav = React.createClass({displayName: "Nav", });
-
-

Usa la REPL di Babel per provare il JSX e vedere come viene trasformato -in JavaScript nativo, e il -convertitore da HTML a JSX per convertire il tuo HTML esistente a -JSX.

- -

Se desideri utilizzare JSX, la guida Primi Passi ti mostra come impostare la compilazione.

- -
-

Nota:

- -

L'espressione JSX viene sempre valutata come un ReactElement. Le implementazioni -attuali potrebbero differire. Un modo ottimizzato potrebbe porre il -ReactElement in linea come un oggetto letterale per evitare il codice di validazione in -React.createElement.

-
-

Namespace dei Componenti #

-

Se stai costruendo un componente che ha parecchi figli, come ad esempio un modulo, potresti facilmente trovarti con una quantità di dichiarazioni di variabili:

-
// Imbarazzante blocco di dichiarazioni di variabili
-var Form = MyFormComponent;
-var FormRow = Form.Row;
-var FormLabel = Form.Label;
-var FormInput = Form.Input;
-
-var App = (
-  <Form>
-    <FormRow>
-      <FormLabel />
-      <FormInput />
-    </FormRow>
-  </Form>
-);
-
-

Per rendere tutto ciò più semplice e leggibile, i componenti con un namespace ti permettono di usare un componente che dispone di altri componenti come proprietà:

-
var Form = MyFormComponent;
-
-var App = (
-  <Form>
-    <Form.Row>
-      <Form.Label />
-      <Form.Input />
-    </Form.Row>
-  </Form>
-);
-
-

Per fare ciò, devi semplicemente creare i tuoi "sub-componenti" come proprietà del componente principale:

-
var MyFormComponent = React.createClass({ ... });
-
-MyFormComponent.Row = React.createClass({ ... });
-MyFormComponent.Label = React.createClass({ ... });
-MyFormComponent.Input = React.createClass({ ... });
-
-

JSX gestirà il tutto correttamente al momento di compilare il tuo codice.

-
var App = (
-  React.createElement(Form, null,
-    React.createElement(Form.Row, null,
-      React.createElement(Form.Label, null),
-      React.createElement(Form.Input, null)
-    )
-  )
-);
-
-
-

Nota:

- -

Questa funzionalità è disponibile nella v0.11 e successive.

-
-

Espressioni JavaScript #

Expressioni come Attributi #

-

Per usare un'espressione JavaScript come valore di un attributo, racchiudi l'espressione in un paio -di parentesi graffe ({}) anziché doppi apici ("").

-
// Input (JSX):
-var person = <Person name={window.isLoggedIn ? window.name : ''} />;
-// Output (JS):
-var person = React.createElement(
-  Person,
-  {name: window.isLoggedIn ? window.name : ''}
-);
-

Attributi Booleani #

-

Omettere il valore di un attributo fa in modo che JSX lo tratti come true. Per passare false occorre utilizzare un'espressione come attributo. Ciò capita spesso quando si usano elementi di moduli HTML, con attributi come disabled, required, checked e readOnly.

-
// Queste due forme sono equivalenti in JSX per disabilitare un bottone
-<input type="button" disabled />;
-<input type="button" disabled={true} />;
-
-// E queste due forme sono equivalenti in JSX per non disabilitare un bottone
-<input type="button" />;
-<input type="button" disabled={false} />;
-

Expressioni per Figli #

-

Similmente, espressioni JavaScript possono essere utilizzate per rappresentare figli:

-
// Input (JSX):
-var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
-// Output (JS):
-var content = React.createElement(
-  Container,
-  null,
-  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
-);
-

Commenti #

-

È facile aggiungere commenti al tuo codice JSX; sono semplici espressioni JS. Devi soltanto prestare attenzione a porre {} attorno ai commenti quando ti trovi dentro la sezione figli di un tag.

-
var content = (
-  <Nav>
-    {/* commento figlio, racchiuso in {} */}
-    <Person
-      /* commento
-         su più
-         righe */
-      name={window.isLoggedIn ? window.name : ''} // fine del commento su una riga
-    />
-  </Nav>
-);
-
-
-

NOTA:

- -

JSX è simile all'HTML, ma non esattamente identico. Consulta la guida JSX gotchas per le differenze fondamentali.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-in-depth-ja-JP.html b/docs/jsx-in-depth-ja-JP.html deleted file mode 100644 index 59a4c22124..0000000000 --- a/docs/jsx-in-depth-ja-JP.html +++ /dev/null @@ -1,658 +0,0 @@ - - - - - - - JSXの深層 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSXの深層 -

-
- -

JSXはXMLに似たJavaScriptのシンタックスの拡張です。Reactでは、単純なJSXのシンタックスの変換を使うことができます。

-

なぜJSXを使うのでしょうか? #

-

ReactでJSXの使用を強制されるわけではありません。生のJSを使うこともできます。しかし、JSXは簡潔で、木構造とReactの特性を定義しやすいシンタックスであるため、JSXを使うことをお勧めします。

- -

デザイナーのようなカジュアルな開発者にとってはさらに馴染みやすいでしょう。

- -

XMLにはバランスの取れた開始タグと終了タグという利益があります。このことで、関数がオブジェクトリテラルを呼んでいるのを読むよりも簡単に大きな木構造を作ることができます。

- -

これはJavaScriptのセマンティックスを代替するものではありません。

-

HTMLタグ対Reactコンポーネント #

-

ReactはHTMLタグ(文字列)とReactコンポーネント(クラス)の両方をレンダリングすることができます。

- -

以下のようにJSXで小文字のタグ名を使用するだけで、HTMLタグをレンダリングできます。

-
var myDivElement = <div className="foo" />;
-ReactDOM.render(myDivElement, document.getElementById('example'));
-
-

以下のように大文字から始まるローカル変数を作成するだけで、Reactのコンポーネントをレンダリングできます。

-
var MyComponent = React.createClass({/*...*/});
-var myElement = <MyComponent someProperty={true} />;
-ReactDOM.render(myElement, document.getElementById('example'));
-
-

ReactのJSXは大文字と小文字を使うことで、ローカルのコンポーネントクラスとHTMLタグを識別する習慣があります。

- -
-

注意:

- -

JSXはJavaScriptなので、 classfor といった識別子はXMLの属性名としては使用しません。代わりに、 ReactのDOMコンポーネントはDOMのプロパティ名がそれぞれ classNamehtmlFor といったものであることを期待します。

-
-

The Transform #

-

ReactのJSXはXMLに似たシンタックスをネイティブなJavaScriptに変換します。XML要素や属性や子要素は React.createElement で渡される引数に変換されます。

-
var Nav;
-// 入力 (JSX):
-var app = <Nav color="blue" />;
-// 出力 (JS):
-var app = React.createElement(Nav, {color:"blue"});
-
-

<Nav /> を使うためには、 Nav 変数がスコープの中にないといけないことに注意してください。

- -

以下のように、JSXはXMLシンタックスを使うことで、細かな子要素の使用も許可します。

-
var Nav, Profile;
-// 入力 (JSX):
-var app = <Nav color="blue"><Profile>click</Profile></Nav>;
-// 出力 (JS):
-var app = React.createElement(
-  Nav,
-  {color:"blue"},
-  React.createElement(Profile, null, "click")
-);
-
-

以下のように、displayNameがundefinedの時には、JSXはクラスのdisplayNameを変数の割り当てから予測します。

-
// 入力 (JSX):
-var Nav = React.createClass({ });
-// 出力 (JS):
-var Nav = React.createClass({displayName: "Nav", });
-
-

JSXを試し、どのようにネイティブなJavaScriptに変換されるか見るには、JSX Compilerを、すでに存在するHTMLをJSXに変換するにはHTMLからJSXへのコンバーターを使ってください。

- -

JSXを使いたい場合は、始めてみましょうというガイドがどのようにコンパイルを設定するか示してくれます。

- -
-

注意:

- -

JSXという表現は常にReactElementを評価します。実際に実行する際の詳細はおそらく異なっているでしょう。最適化されたモードでは React.createElement のコードのバリデーションを避けるためにReactElementをオブジェクトリテラルとして配置するでしょう。

-
-

ネームスペース化されたコンポーネント #

-

formのように、たくさんの子要素を持つコンポーネントを構築する際には、以下のように多くの変数を宣言しなければいけないでしょう。

-
// 変数宣言のあまりよくない部分
-var Form = MyFormComponent;
-var FormRow = Form.Row;
-var FormLabel = Form.Label;
-var FormInput = Form.Input;
-
-var App = (
-  <Form>
-    <FormRow>
-      <FormLabel />
-      <FormInput />
-    </FormRow>
-  </Form>
-);
-
-

これを単純で簡単にするために、 ネームスペース化されたコンポーネント では、以下のように他のコンポーネントを付属物として持つ1つのコンポーネントを使うことができます。

-
var Form = MyFormComponent;
-
-var App = (
-  <Form>
-    <Form.Row>
-      <Form.Label />
-      <Form.Input />
-    </Form.Row>
-  </Form>
-);
-
-

これを行うためには、以下のようにメインコンポーネントの付属物として、「サブコンポーネント」を作るだけで大丈夫です。

-
var MyFormComponent = React.createClass({ ... });
-
-MyFormComponent.Row = React.createClass({ ... });
-MyFormComponent.Label = React.createClass({ ... });
-MyFormComponent.Input = React.createClass({ ... });
-
-

JSXはコードをコンパイルする際にこのプロパティをハンドルします。

-
var App = (
-  React.createElement(Form, null,
-    React.createElement(Form.Row, null,
-      React.createElement(Form.Label, null),
-      React.createElement(Form.Input, null)
-    )
-  )
-);
-
-
-

注意: -この特徴は v0.11 以上で使用できます。

-
-

JavaScriptの表現 #

アトリビュートの表現 #

-

JavaScriptで書いたものをアトリビュートの値として使うためには、その表現を引用("")ではなく波括弧({})で囲ってください。

-
// 入力 (JSX):
-var person = <Person name={window.isLoggedIn ? window.name : ''} />;
-// 出力 (JS):
-var person = React.createElement(
-  Person,
-  {name: window.isLoggedIn ? window.name : ''}
-);
-

Booleanのアトリビュート #

-

アトリビュートの値を記述しないと、JSXはそれを true として扱ってしまいます。false を渡すためには、アトリビュートが使われる必要があります。これらはHTMLのform要素の disabledrequiredcheckedreadOnly といったアトリビュートを使う際によく見かけられます。

-
// 以下の2つはボタンを使用不能にするという意味でJSXでは同義です。
-<input type="button" disabled />;
-<input type="button" disabled={true} />;
-
-// 以下の2つはボタンを使用不能にしないという意味でJSXでは同義です。
-<input type="button" />;
-<input type="button" disabled={false} />;
-

子要素の表現 #

-

同様に、JavaScriptは子要素を表現するのに使われることもあります。

-
// 入力 (JSX):
-var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
-// 出力 (JS):
-var content = React.createElement(
-  Container,
-  null,
-  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
-);
-

コメント #

-

JSXにコメントを加えるのは簡単です。ただのJSの書き方です。タグの内側にコメントを書く時には、 {} で囲うことに注意してください。

-
var content = (
-  <Nav>
-    {/* 子要素にコメントを書く時には、 {} で囲う */}
-    <Person
-      /* 複数
-
-         コメント */
-      name={window.isLoggedIn ? window.name : ''} // 行末コメント
-    />
-  </Nav>
-);
-
-
-

注意: -JSXはHTMLに似ていますが、全く同じではありません。いくつかのキーの違いについてはJSXの理解 をご覧ください。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-in-depth-ko-KR.html b/docs/jsx-in-depth-ko-KR.html deleted file mode 100644 index ded3df1f79..0000000000 --- a/docs/jsx-in-depth-ko-KR.html +++ /dev/null @@ -1,664 +0,0 @@ - - - - - - - JSX 깊이보기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX 깊이보기 -

-
- -

JSX는 XML과 비슷한 JavaScript문법 확장입니다. React에서 변환되는 간단한 JSX 구문을 사용하실 수 있습니다.

-

왜 JSX인가? #

-

React를 위해 꼭 JSX를 사용할 필요는 없고, 그냥 일반 JS를 사용할 수도 있습니만 JSX를 사용하기를 추천합니다. 왜냐하면, 어트리뷰트를 가진 트리 구조로 정의할 수 있는 간결하고 익숙한 문법이기 때문입니다.

- -

이것은 디자이너 같은 케쥬얼 개발자에게 더 익숙합니다.

- -

XML에는 여닫는 태그의 장점이 있습니다. 태그는 큰 트리일 때 함수 호출이나 객체 리터럴보다 읽기 쉬워 집니다.

- -

JSX는 JavaScript의 시맨틱을 변경하지 않습니다.

-

HTML 태그 vs. React 컴포넌트 #

-

React는 렌더 HTML 태그(문자열)이나 React 컴포넌트(클래스)일 수 있습니다.

- -

HTML 태그를 렌더하려면, 그냥 JSX에 소문자 태그를 사용하세요.

-
var myDivElement = <div className="foo" />;
-ReactDOM.render(myDivElement, document.getElementById('example'));
-
-

React 컴포넌트를 렌더하려면, 대문자로 시작하는 로컬 변수를 만드세요.

-
var MyComponent = React.createClass({/*...*/});
-var myElement = <MyComponent someProperty={true} />;
-ReactDOM.render(myElement, document.getElementById('example'));
-
-

React JSX는 대소문자를 로컬 컴포넌트 클래스와 HTML 태그를 구별하는 컨벤션으로 사용합니다.

- -
-

주의:

- -

JSX가 JavaScript기 때문에, class, for같은 식별자는 XML 어트리뷰트 이름으로 -권장하지 않습니다. 대신, React DOM 컴포넌트는 각각 className, htmlFor같은 -DOM 프로퍼티 이름을 기대합니다.

-
-

변환 #

-

React JSX는 XML같은 문법에서 네이티브 JavaScript로 변환됩니다. XML 엘리먼트, 어트리뷰트, 자식은 React.createElement에 넘겨지는 인자로 변환됩니다.

-
var Nav;
-// 입력 (JSX):
-var app = <Nav color="blue" />;
-// 출력 (JS):
-var app = React.createElement(Nav, {color:"blue"});
-
-

<Nav />를 사용하려면, Nav변수는 스코프에 있어야 합니다.

- -

JSX에서는 XML 구문으로 자식을 지정할 수도 있습니다.

-
var Nav, Profile;
-// 입력 (JSX):
-var app = <Nav color="blue"><Profile>click</Profile></Nav>;
-// 출력 (JS):
-var app = React.createElement(
-  Nav,
-  {color:"blue"},
-  React.createElement(Profile, null, "click")
-);
-
-

클래스에 displayName이 정의되어 있지 않으면 JSX는 변수명을 displayName으로 간주할 것입니다:

-
// 입력 (JSX):
-var Nav = React.createClass({ });
-// 출력 (JS):
-var Nav = React.createClass({displayName: "Nav", });
-
-

바벨 REPL를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, HTML-JSX 변환기는 이미 있는 HTML을 JSX로 변환해 줍니다.

- -

JSX를 사용 하시려면, 시작하기 가이드에서 어떻게 컴파일을 하기 위해 설정하는지 보실 수 있습니다.

- -
-

주의:

- -

JSX 표현식은 언제나 ReactElement로 변환됩니다. 실제 구현의 세부사항은 많이 -다를 수 있습니다. 최적화 모드는 ReactElement를 React.createElement에서 검증 -코드를 우회하는 객체 리터럴로 ReactElement를 인라인으로 만들 수 있습니다.

-
-

네임스페이스를 사용한 컴포넌트 #

-

폼같은 자식을 많이 가지는 컴포넌트를 만든다면, 많은 변수 선언을 하게 될 것입니다.

-
// 변수 선언의 어색한 블록
-var Form = MyFormComponent;
-var FormRow = Form.Row;
-var FormLabel = Form.Label;
-var FormInput = Form.Input;
-
-var App = (
-  <Form>
-    <FormRow>
-      <FormLabel />
-      <FormInput />
-    </FormRow>
-  </Form>
-);
-
-

더 간단하고 쉽게 네임스페이스를 사용한 컴포넌트를 사용해서, 다른 컴포넌트를 어트리뷰트로 가지는 하나의 컴포넌트만 쓸 수 있습니다.

-
var Form = MyFormComponent;
-
-var App = (
-  <Form>
-    <Form.Row>
-      <Form.Label />
-      <Form.Input />
-    </Form.Row>
-  </Form>
-);
-
-

이렇게 하려면, "sub-components"를 메인 컴포넌트의 어트리뷰트로 만들 필요가 있습니다.

-
var MyFormComponent = React.createClass({ ... });
-
-MyFormComponent.Row = React.createClass({ ... });
-MyFormComponent.Label = React.createClass({ ... });
-MyFormComponent.Input = React.createClass({ ... });
-
-

코드를 컴파일할 때 JSX는 이것을 제대로 처리해 줍니다.

-
var App = (
-  React.createElement(Form, null,
-    React.createElement(Form.Row, null,
-      React.createElement(Form.Label, null),
-      React.createElement(Form.Input, null)
-    )
-  )
-);
-
-
-

주의:

- -

이 기능은 v0.11 이상에만 있습니다.

-
-

JavaScript 표현식 #

어트리뷰트 표현식 #

-

JavaScript 표현식을 어트리뷰트 값으로 사용하려면, 표현식을 쌍따옴표("")대신 중괄호({})로 감싸야 합니다.

-
// 입력 (JSX):
-var person = <Person name={window.isLoggedIn ? window.name : ''} />;
-// 출력 (JS):
-var person = React.createElement(
-  Person,
-  {name: window.isLoggedIn ? window.name : ''}
-);
-

불린 어트리뷰트 #

-

어트리뷰트의 값을 생략하면 JSX는 값을 true로 취급합니다. 어트리뷰트 표현식에 false를 넘기려면 사용해야만 합니다. HTML 폼 엘리먼트에 disabled, required, checked, readOnly같은 어트리뷰트를 사용할 일이 자주 있습니다.

-
// JSX에서 이 두 줄은 똑같이 버튼을 비활성화합니다.
-<input type="button" disabled />;
-<input type="button" disabled={true} />;
-
-// 그리고 JSX에서 이 두 줄은 똑같이 버튼을 비활성화하지 않습니다.
-<input type="button" />;
-<input type="button" disabled={false} />;
-

자식 표현식 #

-

비슷하게, JavaScript 표현식을 자식을 표현하는 데 사용할 수 있습니다.

-
// 입력 (JSX):
-var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
-// 출력 (JS):
-var content = React.createElement(
-  Container,
-  null,
-  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
-);
-

주석 #

-

JSX에 주석을 넣기는 쉽습니다. 그냥 JS 표현식과 같습니다. 그냥 태그의 자식 섹션에서만 조심하시면 됩니다. 이럴 땐 주석 주변에 {}를 감싸야 합니다.

-
var content = (
-  <Nav>
-    {/* 자식 주석, {}로 감싼다 */}
-    <Person
-      /* 여러
-
-         주석 */
-      name={window.isLoggedIn ? window.name : ''} // 줄 끝부분 주석
-    />
-  </Nav>
-);
-
-
-

주의:

- -

JSX 는 HTML과 비슷하지만 완전히 같지는 않습니다. 중요한 차이점을 보시려면 JSX gotchas를 보세요.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-in-depth-zh-CN.html b/docs/jsx-in-depth-zh-CN.html deleted file mode 100644 index f2ca8a8b64..0000000000 --- a/docs/jsx-in-depth-zh-CN.html +++ /dev/null @@ -1,663 +0,0 @@ - - - - - - - 深入 JSX | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 深入 JSX -

-
- -

JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。React 可以用来做简单的 JSX 句法转换。

-

为什么要用 JSX? #

-

你不需要为了 React 使用 JSX,可以直接使用原生 JS。但是,我们建议使用 JSX 是因为它能精确,也是常用的定义包含属性的树状结构的语法。

- -

它对于非专职开发者比如设计师也比较熟悉。

- -

XML 有固定的标签开启和闭合的优点。这能让复杂的树更易于阅读,优于方法调用和对象字面量的形式。

- -

它没有修改 JavaScript 语义。

-

HTML 标签对比 React 组件 #

-

React 可以渲染 HTML 标签 (strings) 或 React 组件 (classes)。

- -

要渲染 HTML 标签,只需在 JSX 里使用小写字母的标签名。

-
var myDivElement = <div className="foo" />;
-ReactDOM.render(myDivElement, document.getElementById('example'));
-
-

要渲染 React 组件,只需创建一个大写字母开头的本地变量。

-
var MyComponent = React.createClass({/*...*/});
-var myElement = <MyComponent someProperty={true} />;
-ReactDOM.render(myElement, document.getElementById('example'));
-
-

React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标签。

- -
-

注意:

- -

由于 JSX 就是 JavaScript,一些标识符像 classfor 不建议作为 XML -属性名。作为替代,React DOM 使用 classNamehtmlFor 来做对应的属性。

-
-

转换(Transform) #

-

JSX 把类 XML 的语法转成原生 JavaScript,XML 元素、属性和子节点被转换成 React.createElement 的参数。

-
var Nav;
-// 输入 (JSX):
-var app = <Nav color="blue" />;
-// 输出 (JS):
-var app = React.createElement(Nav, {color:"blue"});
-
-

注意,要想使用 <Nav />Nav 变量一定要在作用区间内。

- -

JSX 也支持使用 XML 语法定义子结点:

-
var Nav, Profile;
-// 输入 (JSX):
-var app = <Nav color="blue"><Profile>click</Profile></Nav>;
-// 输出 (JS):
-var app = React.createElement(
-  Nav,
-  {color:"blue"},
-  React.createElement(Profile, null, "click")
-);
-
-

当显示名称没有定义时,JSX 会根据变量赋值来推断类的 显示名称 :

-
// 输入 (JSX):
-var Nav = React.createClass({ });
-// 输出 (JS):
-var Nav = React.createClass({displayName: "Nav", });
-
-

使用 JSX 编译器 来试用 JSX 并理解它是如何转换到原生 JavaScript,还有 HTML 到 JSX 转换器 来把现有 HTML 转成 JSX。

- -

如果你要使用 JSX,这篇 新手入门 教程来教你如何搭建环境。

- -
-

注意:

- -

JSX 表达式总是会当作 ReactElement 执行。具体的实际细节可能不同。一种优化 -的模式是把 ReactElement 当作一个行内的对象字面量形式来绕过 -React.createElement 里的校验代码。

-
-

命名组件(Namespaced Components) #

-

如果你正在构建一个有很多子组件的组件,比如表单,你也许会最终得到许多的变量声明。

-
// 尴尬的变量声明块
-var Form = MyFormComponent;
-var FormRow = Form.Row;
-var FormLabel = Form.Label;
-var FormInput = Form.Input;
-
-var App = (
-  <Form>
-    <FormRow>
-      <FormLabel />
-      <FormInput />
-    </FormRow>
-  </Form>
-);
-
-

为了使其更简单和容易,命名组件令你使用包含其他组件作为属性的单一的组件。

-
var Form = MyFormComponent;
-
-var App = (
-  <Form>
-    <Form.Row>
-      <Form.Label />
-      <Form.Input />
-    </Form.Row>
-  </Form>
-);
-
-

要做到这一点,你只需要把你的"子组件"创建为主组件的属性。

-
var MyFormComponent = React.createClass({ ... });
-
-MyFormComponent.Row = React.createClass({ ... });
-MyFormComponent.Label = React.createClass({ ... });
-MyFormComponent.Input = React.createClass({ ... });
-
-

当编译你的代码时,JSX会恰当的进行处理。

-
var App = (
-  React.createElement(Form, null,
-    React.createElement(Form.Row, null,
-      React.createElement(Form.Label, null),
-      React.createElement(Form.Input, null)
-    )
-  )
-);
-
-
-

注意:

- -

此特性在 v0.11 及以上可用.

-
-

JavaScript 表达式 #

属性表达式 #

-

要使用 JavaScript 表达式作为属性值,只需把这个表达式用一对大括号 ({}) 包起来,不要用引号 ("")。

-
// 输入 (JSX):
-var person = <Person name={window.isLoggedIn ? window.name : ''} />;
-// 输出 (JS):
-var person = React.createElement(
-  Person,
-  {name: window.isLoggedIn ? window.name : ''}
-);
-

Boolean 属性 #

-

省略一个属性的值会导致JSX把它当做 true。要传值 false必须使用属性表达式。这常出现于使用HTML表单元素,含有属性如disabled, required, checkedreadOnly

-
// 在JSX中,对于禁用按钮这二者是相同的。
-<input type="button" disabled />;
-<input type="button" disabled={true} />;
-
-// 在JSX中,对于不禁用按钮这二者是相同的。
-<input type="button" />;
-<input type="button" disabled={false} />;
-

子节点表达式 #

-

同样地,JavaScript 表达式可用于描述子结点:

-
// 输入 (JSX):
-var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
-// 输出 (JS):
-var content = React.createElement(
-  Container,
-  null,
-  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
-);
-

注释 #

-

JSX 里添加注释很容易;它们只是 JS 表达式而已。你仅仅需要小心的是当你在一个标签的子节点块时,要用 {} 包围要注释的部分。

-
var content = (
-  <Nav>
-    {/* child comment, 用 {} 包围 */}
-    <Person
-      /* 多
-
-         注释 */
-      name={window.isLoggedIn ? window.name : ''} // 行尾注释
-    />
-  </Nav>
-);
-
-
-

注意:

- -

JSX 类似于 HTML,但不完全一样。参考 JSX 陷阱 了解主要不同。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-in-depth.html b/docs/jsx-in-depth.html index 0729362761..730fa6d551 100644 --- a/docs/jsx-in-depth.html +++ b/docs/jsx-in-depth.html @@ -1,12 +1,14 @@ + + - JSX in Depth | React - - + JSX In Depth - React + + @@ -44,31 +46,275 @@
-
+
+ Edit on GitHub +

+ JSX In Depth +

+
+ +

Fundamentally, JSX just provides syntactic sugar for the React.createElement(component, props, ...children) function. The JSX code:

+
<MyButton color="blue" shadowSize={2}>Click Me</MyButton>
+
+

compiles into:

+
React.createElement(MyButton, {color: "blue", shadowSize: 2}, 'Click Me')
+
+

You can also use the self-closing form of the tag if there are no children. So:

+
<div className="sidebar" />
+
+

compiles into:

+
React.createElement('div', {className: 'sidebar'}, null)
+
+

If you want to test out how some specific JSX is converted into JavaScript, you can try out the online Babel compiler.

+

Specifying The React Element Type #

+

The first part of a JSX tag determines the type of the React element.

+ +

Capitalized types indicate that the JSX tag is referring to a React component. These tags get compiled into a direct reference to the named variable, so if you use the JSX <Foo /> expression, Foo must be in scope.

+ +

Since JSX compiles into calls to React.createElement, the React library must also always be in scope from your JSX code.

+ +

For example, both of the imports are necessary in this code, even though 'React' and 'CustomButton' are not directly referenced from JavaScript:

+
import React from 'react';
+import CustomButton from './CustomButton';
+
+function WarningButton() {
+  return <CustomButton color="red" />;
+}
+
+

If you don't use a JavaScript bundler and added React as a script tag, it is already in scope as a React global.

+ +

You can also refer to a React component using dot-notation from within JSX. This is convenient if you have a single module that exports many React components. For example, if MyComponents.DatePicker is a component, you can use it directly from JSX with:

+
import React from 'react';
+
+var MyComponents = {
+  DatePicker: function(props) {
+    return <div>imagine a {props.color} datepicker here</div>;
+  }
+}
+
+function BlueDatePicker() {
+  return <MyComponents.DatePicker color="blue"} />;
+}
+
+

When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like <Foo /> compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.

+ +

We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.

+ +

For example, this code will not run as expected:

+
import React from 'react';
+
+function hello(props) {
+  // This use of <div> is legitimate because div is a valid HTML tag
+  return <div>Hello {props.toWhat}</div>;
+}
+
+function HelloWorld() {
+  // This code attempts to create an HTML <hello> tag and fails
+  return <hello toWhat="World" />;
+}
+
+

You cannot use a general expression as the React element type. If you do want to use a general expression to indicate the type of the element, just assign it to a capitalized variable first. This often comes up when you want to render a different component based on a prop:

+
import React from 'react';
+import { PhotoStory, VideoStory } from './stories';
+
+const components = {
+  photo: <PhotoStory />,
+  video: <VideoStory />,
+};
+
+function Story1(props) {
+  // Not valid JSX
+  return <components[props.story] />;
+}
+
+function render2(props) {
+  var MyComponent = components[props.story];
+
+  // Valid JSX
+  return <MyComponent />;
+}
+

Props in JSX #

+

There are several different ways to specify props in JSX.

+

JavaScript Expressions #

+

You can pass any JavaScript expression as a prop, by surrounding it with {}. For example, in this JSX:

+
<MyComponent foo={1 + 2 + 3 + 4} />
+
+

For MyComponent, The value of props.foo will be 10 because the expression 1 + 2 + 3 + 4 gets evaluated.

+ +

if statements and for loops are not expressions in JavaScript, so they can't be used in JSX directly. Instead, you can put these in the surrounding code. For example:

+
function NumberDescriber(props) {
+  var description;
+  if (props.number % 2 == 0) {
+    description = <strong>even</strong>;
+  } else {
+    description = <i>odd</i>;
+  }
+  return <div>{props.number} is an {description} number</div>;
+}
+

String Literals #

+

You can pass a string literal as a prop. These two JSX expressions are equivalent:

+
<MyComponent message="hello world" />
+
+<MyComponent message={"hello world"} />
+
+

When you pass a string literal, its value is HTML-unescaped. So these two JSX expressions are equivalent:

+
<MyComponent message="&lt;3" />
+
+<MyComponent message={"<3"} />
+
+

This behavior is usually not relevant. It's only mentioned here for completeness.

+

Props Default to "True" #

+

If you pass no value for a prop, it defaults to true. These two JSX expressions are equivalent:

+
<MyTextBox autocomplete />
+
+<MyTextBox autocomplete={true} />
+
+

In general, we don't recommend using this because it can be confused with the ES6 object shorthand {foo} which is short for {foo: foo} rather than {foo: true}. This behavior is just there so that it matches the behavior of HTML.

+

Spread Attributes #

+

If you already have props as an object, and you want to pass it in JSX, you can use ... as a "spread" operator to pass the whole props object. These two render functions are equivalent:

+
function render1() {
+  var props = {left: 'ben', right: 'hector'};
+  return <MyComponent {...props} />;
+}
+
+function render2() {
+  return <MyComponent left="ben" right="hector" />;
+}
+
+

Spread attributes can be useful when you are building generic containers. However, they can also make your code messy by making it easy to pass a lot of irrelevant props to components that don't care about them. We recommend that you use this syntax sparingly.

+

Children in JSX #

+

In JSX expressions that contain both an opening tag and a closing tag, the content between those tags is passed as a special prop: props.children. There are several different ways to pass children:

+

String Literals #

+

You can put a string between the opening and closing tags and props.children will just be that string. This is useful for many of the built-in HTML elements. For example:

+
<MyComponent>Hello world!</MyComponent>
+
+

This is valid JSX, and props.children in MyComponent will simply be the string "Hello world!". HTML is unescaped, so you can generally write JSX just like you would write HTML in this way:

+
<div>This is valid HTML &amp; JSX at the same time.</div>
+
+

JSX removes whitespace at the beginning and ending of a line. It also removes blank lines. New lines adjacent to tags are removed; new lines that occur in the middle of string literals are condensed into a single space. So these all render to the same thing:

+
<div>Hello World</div>
+
+<div>
+  Hello World
+</div>
+
+<div>
+  Hello
+  World
+</div>
+
+<div>
+
+  Hello World
+</div>
+

JSX Children #

+

You can provide more JSX elements as the children. This is useful for displaying nested components:

+
<MyContainer>
+  <MyFirstComponent />
+  <MySecondComponent />
+</MyContainer>
+
+

You can mix together different types of children, so you can use string literals together with JSX children. This is another way in which JSX is like HTML, so that this is both valid JSX and valid HTML:

+
<div>
+  Here is a list:
+  <ul>
+    <li>Item 1</li>
+    <li>Item 2</li>
+  </ul>
+</div>
+
+

A React component can't return multiple React elements, but a single JSX expression can have multiple children, so if you want a component to render multiple things you can wrap it in a div like this.

+

JavaScript Expressions #

+

You can pass any JavaScript expression as children, by enclosing it within {}. For example, these expressions are equivalent:

+
<MyComponent>foo</MyComponent>
+
+<MyComponent>{'foo'}</MyComponent>
+
+

This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this renders an HTML list:

+
function Item(props) {
+  return <li>{props.message}</li>;
+}
+
+function renderTodoList() {
+  var todos = ['finish doc', 'submit pr', 'nag dan to review'];
+  return (
+    <ul>
+      {todos.map((message) => <Item key={message} message={message} />)}
+    </ul>
+  );
+}
+
+

JavaScript expressions can be mixed with other types of children. This is often useful in lieu of string templates:

+
function Hello(props) {
+  return <div>Hello {props.addressee}!</div>;
+}
+
+

Normally, JavaScript expressions inserted in JSX will evaluate to a string, a React element, or a list of those things. However, props.children works just like any other prop in that it can pass any sort of data, not just the sorts that React knows how to render. For example, if you have a custom component, you could have it take a callback as props.children:

+
function ListOfTenThings() {
+  return (
+    <Repeat numTimes={10}>
+      {(index) => <div key={index}>This is item {index} in the list</div>}
+    </Repeat>
+  );
+}
+
+// Calls the children callback numTimes to produce a repeated component
+function Repeat(props) {
+  var items = [];
+  for (var i = 0; i < numTimes; i++) {
+    items.push(props.children(i));
+  }
+  return <div>{items}</div>
+}
+
+

Children passed to a custom component can be anything, as long as that component transforms them into something React can understand before rendering. This usage is not common, but it works if you want to stretch what JSX is capable of.

+ +

false, null, 'undefined', and 'true' are valid children. They simply don't render. These JSX expressions will all render to the same thing:

+
<div />
+
+<div></div>
+
+<div>{false}</div>
+
+<div>{null}</div>
+
+<div>{true}</div>
+
+

This can be useful to conditionally render React elements. This JSX only renders a <Header /> if showHeader is true:

+
<div>{showHeader && <Header />}<Content /></div>
+
+ +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,210 +549,57 @@
+ - -
- Edit on GitHub -

- JSX in Depth -

-
- -

JSX is a JavaScript syntax extension that looks similar to XML. You can use a simple JSX syntactic transform with React.

-

Why JSX? #

-

You don't have to use JSX with React. You can just use plain JS. However, we recommend using JSX because it is a concise and familiar syntax for defining tree structures with attributes.

- -

It's more familiar for casual developers such as designers.

- -

XML has the benefit of balanced opening and closing tags. This helps make large trees easier to read than function calls or object literals.

- -

It doesn't alter the semantics of JavaScript.

-

HTML Tags vs. React Components #

-

React can either render HTML tags (strings) or React components (classes).

- -

To render an HTML tag, just use lower-case tag names in JSX:

-
var myDivElement = <div className="foo" />;
-ReactDOM.render(myDivElement, document.getElementById('example'));
-
-

To render a React Component, just create a local variable that starts with an upper-case letter:

-
var MyComponent = React.createClass({/*...*/});
-var myElement = <MyComponent someProperty={true} />;
-ReactDOM.render(myElement, document.getElementById('example'));
-
-

React's JSX uses the upper vs. lower case convention to distinguish between local component classes and HTML tags.

- -
-

Note:

- -

Since JSX is JavaScript, identifiers such as class and for are discouraged -as XML attribute names. Instead, React DOM components expect DOM property -names like className and htmlFor, respectively.

-
-

The Transform #

-

React JSX transforms from an XML-like syntax into native JavaScript. XML elements, attributes and children are transformed into arguments that are passed to React.createElement.

-
var Nav;
-// Input (JSX):
-var app = <Nav color="blue" />;
-// Output (JS):
-var app = React.createElement(Nav, {color:"blue"});
-
-

Notice that in order to use <Nav />, the Nav variable must be in scope.

- -

JSX also allows specifying children using XML syntax:

-
var Nav, Profile;
-// Input (JSX):
-var app = <Nav color="blue"><Profile>click</Profile></Nav>;
-// Output (JS):
-var app = React.createElement(
-  Nav,
-  {color:"blue"},
-  React.createElement(Profile, null, "click")
-);
-
-

JSX will infer the class's displayName from the variable assignment when the displayName is undefined:

-
// Input (JSX):
-var Nav = React.createClass({ });
-// Output (JS):
-var Nav = React.createClass({displayName: "Nav", });
-
-

Use the Babel REPL to try out JSX and see how it desugars into native JavaScript, and the HTML to JSX converter to convert your existing HTML to JSX.

- -

If you want to use JSX, the Getting Started guide shows how to set up compilation.

- -
-

Note:

- -

The JSX expression always evaluates to a ReactElement. The actual -implementation details may vary. An optimized mode could inline the -ReactElement as an object literal to bypass the validation code in -React.createElement.

-
-

Namespaced Components #

-

If you are building a component that has many children, like a form, you might end up with something with a lot of variable declarations:

-
// Awkward block of variable declarations
-var Form = MyFormComponent;
-var FormRow = Form.Row;
-var FormLabel = Form.Label;
-var FormInput = Form.Input;
-
-var App = (
-  <Form>
-    <FormRow>
-      <FormLabel />
-      <FormInput />
-    </FormRow>
-  </Form>
-);
-
-

To make it simpler and easier, namespaced components let you use one component that has other components as attributes:

-
var Form = MyFormComponent;
-
-var App = (
-  <Form>
-    <Form.Row>
-      <Form.Label />
-      <Form.Input />
-    </Form.Row>
-  </Form>
-);
-
-

To do this, you just need to create your "sub-components" as attributes of the main component:

-
var MyFormComponent = React.createClass({ ... });
-
-MyFormComponent.Row = React.createClass({ ... });
-MyFormComponent.Label = React.createClass({ ... });
-MyFormComponent.Input = React.createClass({ ... });
-
-

JSX will handle this properly when compiling your code.

-
var App = (
-  React.createElement(Form, null,
-    React.createElement(Form.Row, null,
-      React.createElement(Form.Label, null),
-      React.createElement(Form.Input, null)
-    )
-  )
-);
-
-
-

Note:

- -

This feature is available in v0.11 and above.

-
-

JavaScript Expressions #

Attribute Expressions #

-

To use a JavaScript expression as an attribute value, wrap the expression in a pair of curly braces ({}) instead of quotes ("").

-
// Input (JSX):
-var person = <Person name={window.isLoggedIn ? window.name : ''} />;
-// Output (JS):
-var person = React.createElement(
-  Person,
-  {name: window.isLoggedIn ? window.name : ''}
-);
-

Boolean Attributes #

-

Omitting the value of an attribute causes JSX to treat it as true. To pass false an attribute expression must be used. This often comes up when using HTML form elements, with attributes like disabled, required, checked and readOnly.

-
// These two are equivalent in JSX for disabling a button
-<input type="button" disabled />;
-<input type="button" disabled={true} />;
-
-// And these two are equivalent in JSX for not disabling a button
-<input type="button" />;
-<input type="button" disabled={false} />;
-

Child Expressions #

-

Likewise, JavaScript expressions may be used to express children:

-
// Input (JSX):
-var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
-// Output (JS):
-var content = React.createElement(
-  Container,
-  null,
-  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
-);
-

Comments #

-

It's easy to add comments within your JSX; they're just JS expressions. You just need to be careful to put {} around the comments when you are within the children section of a tag.

-
var content = (
-  <Nav>
-    {/* child comment, put {} around */}
-    <Person
-      /* multi
-         line
-         comment */
-      name={window.isLoggedIn ? window.name : ''} // end of line comment
-    />
-  </Nav>
-);
-
-
-

NOTE:

- -

JSX is similar to HTML, but not exactly the same. See JSX gotchas for some key differences.

-
- - -
- - ← Prev - - - Next → - -
-
- - -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Attributi Spread JSX -

-
- -

Se sai in anticipo che tutte le proprietà che desideri assegnare ad un componente, usare JSX è facile:

-
  var component = <Component foo={x} bar={y} />;
-

Le Props Mutevoli sono il Male #

-

Se non sai quali proprietà desideri impostare, potresti essere tentato di aggiungerle all'oggetto in seguito:

-
  var component = <Component />;
-  component.props.foo = x; // male
-  component.props.bar = y; // altrettanto male
-
-

Questo è un anti-pattern perché significa che non possiamo aiutarti a verificare i propTypes per tempo. Ciò significa che i tuoi errori di propTypes finiscono per avere uno stack trace indecifrabile.

- -

Le props dovrebbero essere considerate immutabili. Mutare l'oggetto props altrove potrebbe causare conseguenze inattese, quindi a questo punto dovrebbe essere idealmente considerato un oggetto congelato.

-

Attributi Spread #

-

Adesso puoi utilizzare una nuova caratteristica di JSX chiamata attributi spread:

-
  var props = {};
-  props.foo = x;
-  props.bar = y;
-  var component = <Component {...props} />;
-
-

Le proprietà dell'oggetto che passi al componente sono copiate nelle sue props.

- -

Puoi usarlo più volte o combinarlo con altri attributi. L'ordine in cui sono specificati è rilevante. Attributi successivi ridefiniscono quelli precedentemente impostati.

-
  var props = { foo: 'default' };
-  var component = <Component {...props} foo={'override'} />;
-  console.log(component.props.foo); // 'override'
-

Cos'è la strana notazione ...? #

-

L'operatore ... (o operatore spread) è già supportato per gli array in ES6. Esiste anche una proposta per ES7 per le proprietà Spread e Rest di Object. Stiamo prendendo spunto da questi standard supportati o in corso di sviluppo per fornire una sintassi più pulita a JSX.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-spread-ja-JP.html b/docs/jsx-spread-ja-JP.html deleted file mode 100644 index 3c190b6f9d..0000000000 --- a/docs/jsx-spread-ja-JP.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - - - - JSXの拡張属性 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSXの拡張属性 -

-
- -

以下のように、コンポーネントにどのようなプロパティを配置したいか前もって全て分かっている場合は、JSXを使うことは簡単です。

-
  var component = <Component foo={x} bar={y} />;
-

Propsを変更してはいけない #

-

セットしたいプロパティが分からない場合は、以下のように後からオブジェクトに追加したいと思うでしょう。

-
  var component = <Component />;
-  component.props.foo = x; // だめ
-  component.props.bar = y; // 同様にだめ
-
-

これはアンチパターンです。なぜなら、後々まで正しいpropTypesであるかどうかチェックすることを助けることができないことを意味するからです。これは、propTypesのエラーが隠されたスタックトレースに出力されて終わってしまうことを意味します。

- -

propsは変更不可と考えられるべきです。propsのオブジェクトをどこかで変更することは予期せぬ結果を発生させる可能性があるので、理想的には、この時点ではpropsは固定のオブジェクトであるべきです。

-

拡張属性 #

-

以下のように、拡張属性というJSXの新しい特徴を使うことができます。

-
  var props = {};
-  props.foo = x;
-  props.bar = y;
-  var component = <Component {...props} />;
-
-

あなたが渡したオブジェクトのプロパティはコンポーネントのpropsにコピーされます。

- -

これを複数回使用したり、他の属性と組み合わせたりすることもできます。仕様書では、順序が重要となっています。後の属性は前の属性をオーバーライドします。

-
  var props = { foo: 'default' };
-  var component = <Component {...props} foo={'override'} />;
-  console.log(component.props.foo); // 'override'
-

奇妙な ... という表現は何でしょうか? #

-

... 操作(拡張操作)は既にES6のarraysでサポートされています。Object Rest と Spread PropertiesのES7のプロポーザルもあります。JSXのきれいなシンタックスを供給するために、それらのサポートや開発中の標準使用を利用しています。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-spread-ko-KR.html b/docs/jsx-spread-ko-KR.html deleted file mode 100644 index ea9a3163d4..0000000000 --- a/docs/jsx-spread-ko-KR.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - - - - JSX 스프레드 어트리뷰트 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX 스프레드 어트리뷰트 -

-
- -

미리 컴포넌트에 넣을 모든 프로퍼티를 알게 된다면, JSX를 사용하기 쉬워집니다.

-
  var component = <Component foo={x} bar={y} />;
-

Props의 변경은 나빠요 #

-

하지만 어떤 프로퍼티를 설정하고 싶은지 모른다면, 객체 레이어에 넣고 싶어질 수도 있습니다.

-
  var component = <Component />;
-  component.props.foo = x; // 나쁨
-  component.props.bar = y; // 역시 나쁨
-
-

이것은 안티 패턴입니다. 왜냐하면 한참 뒤까지 정확한 propTypes을 체크할 수 없다는 뜻이기 때문입니다. 이것은 propTypes 에러는 알기 힘든 스택 트레이스로 끝난다는 의미입니다.

- -

props는 변하지 않는 것으로 간주해야 합니다. props 객체를 변경하는 것은 다른 곳에서 예기치 못한 결과가 생길 수 있기 때문에 이상적으로는 이 시점에서 frozen 객체가 되어야 합니다.

-

스프레드 어트리뷰트 #

-

이제 JSX의 새로운 기능인 스프레드 어트리뷰트를 사용하실 수 있습니다.

-
  var props = {};
-  props.foo = x;
-  props.bar = y;
-  var component = <Component {...props} />;
-
-

전달한 객체의 프로퍼티가 컴포넌트의 props에 복사됩니다.

- -

이렇게 여러 번 사용하거나 다른 어트리뷰트와 조합해서 사용할 수 있습니다. 명세의 순서는 중요합니다. 나중의 어트리뷰트가 이전 것보다 우선되기 때문입니다.

-
  var props = { foo: 'default' };
-  var component = <Component {...props} foo={'override'} />;
-  console.log(component.props.foo); // 'override'
-

이상한 ... 표기법은 무엇인가요? #

-

... 연산자(스프레드 연산자)는 이미 ES6의 배열에서 지원합니다. 객체 rest와 스프레드 프로퍼티에 대한 ES7의 제안도 있습니다. JSX의 구문을 더 깔끔하게 하기 위해 지원되고 개발중인 표준을 활용하고 있습니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-spread-zh-CN.html b/docs/jsx-spread-zh-CN.html deleted file mode 100644 index 07438dfac5..0000000000 --- a/docs/jsx-spread-zh-CN.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - - - - JSX 展开属性 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX 展开属性 -

-
- -

如果你事先知道组件需要的全部 Props(属性),JSX 很容易地这样写:

-
  var component = <Component foo={x} bar={y} />;
-

修改 Props 是不好的,明白吗 #

-

如果你不知道要设置哪些 Props,那么现在最好不要设置它:

-
  var component = <Component />;
-  component.props.foo = x; // 不好
-  component.props.bar = y; // 同样不好
-
-

这样是反模式,因为 React 不能帮你检查属性类型(propTypes)。这样即使你的 属性类型有错误也不能得到清晰的错误提示。

- -

Props 应该被认为是不可变的。在别处修改 props 对象可能会导致预料之外的结果,所以原则上这将是一个冻结的对象。

-

展开属性(Spread Attributes) #

-

现在你可以使用 JSX 的新特性 - 展开属性:

-
  var props = {};
-  props.foo = x;
-  props.bar = y;
-  var component = <Component {...props} />;
-
-

传入对象的属性会被复制到组件内。

- -

它能被多次使用,也可以和其它属性一起用。注意顺序很重要,后面的会覆盖掉前面的。

-
  var props = { foo: 'default' };
-  var component = <Component {...props} foo={'override'} />;
-  console.log(component.props.foo); // 'override'
-

这个奇怪的 ... 标记是什么? #

-

这个 ... 操作符(增强的操作符)已经被 ES6 数组 支持。相关的还有 ECMAScript 规范草案中的 Object 剩余和展开属性(Rest and Spread Properties)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/jsx-spread.html b/docs/jsx-spread.html deleted file mode 100644 index 2eb8f20232..0000000000 --- a/docs/jsx-spread.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - - - - JSX Spread Attributes | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- JSX Spread Attributes -

-
- -

If you know all the properties that you want to place on a component ahead of time, it is easy to use JSX:

-
  var component = <Component foo={x} bar={y} />;
-

Mutating Props is Bad #

-

If you don't know which properties you want to set, you might be tempted to add them onto the object later:

-
  var component = <Component />;
-  component.props.foo = x; // bad
-  component.props.bar = y; // also bad
-
-

This is an anti-pattern because it means that we can't help you check the right propTypes until way later. This means that your propTypes errors end up with a cryptic stack trace.

- -

The props should be considered immutable. Mutating the props object somewhere else could cause unexpected consequences so ideally it would be a frozen object at this point.

-

Spread Attributes #

-

Now you can use a new feature of JSX called spread attributes:

-
  var props = {};
-  props.foo = x;
-  props.bar = y;
-  var component = <Component {...props} />;
-
-

The properties of the object that you pass in are copied onto the component's props.

- -

You can use this multiple times or combine it with other attributes. The specification order is important. Later attributes override previous ones.

-
  var props = { foo: 'default' };
-  var component = <Component {...props} foo={'override'} />;
-  console.log(component.props.foo); // 'override'
-

What's with the weird ... notation? #

-

The ... operator (or spread operator) is already supported for arrays in ES6. There is also an ECMAScript proposal for Object Rest and Spread Properties. We're taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/language-tooling.html b/docs/language-tooling.html deleted file mode 100644 index 32109c926a..0000000000 --- a/docs/language-tooling.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - - - - Language Tooling | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Language Tooling -

-
- -

ES2015 with JSX #

In-browser JSX Transform #

-

If you like using JSX, Babel 5 provided an in-browser ES2015 and JSX transformer for development called browser.js that can be included from CDNJS. Include a <script type="text/babel"> tag to engage the JSX transformer.

- -
-

Note:

- -

The in-browser JSX transformer is fairly large and results in extraneous computation client-side that can be avoided. Do not use it in production — see the next section.

-
-

Productionizing: Precompiled JSX #

-

If you have npm, you can run npm install -g babel-cli. Babel has built-in support for React v0.12+. Tags are automatically transformed to their equivalent React.createElement(...), displayName is automatically inferred and added to all React.createClass calls.

- -

This tool will translate files that use JSX syntax to plain JavaScript files that can run directly in the browser. It will also watch directories for you and automatically transform files when they are changed; for example: babel --watch src/ --out-dir lib/.

- -

Beginning with Babel 6, there are no transforms included by default. This means that options must be specified when running the babel command, or a .babelrc must specify options. Additional packages must also be installed which bundle together a number of transforms, called presets. The most common use when working with React will be to include the es2015 and react presets. More information about the changes to Babel can be found in their blog post announcing Babel 6.

- -

Here is an example of what you will do if using ES2015 syntax and React:

-
npm install babel-preset-es2015 babel-preset-react
-babel --presets es2015,react --watch src/ --out-dir lib/
-
-

By default JSX files with a .js extension are transformed. Run babel --help for more information on how to use Babel.

- -

Example output:

-
$ cat test.js
-function HelloMessage(props) {
-  return <div>Hello {props.name}</div>;
-}
-
-ReactDOM.render(<HelloMessage name="John" />, mountNode);
-
-$ babel test.js
-"use strict";
-
-function HelloMessage(props) {
-  return React.createElement(
-    "div",
-    null,
-    "Hello ",
-    props.name
-  );
-}
-
-ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
-

Helpful Open-Source Projects #

-

The open-source community has built tools that integrate JSX with several editors and build systems. See JSX integrations for the full list.

-

Flow #

-

Flow is a JavaScript type checker released by Facebook, and it supports JSX. For more info, checkout the Flow homepage.

-

TypeScript #

-

TypeScript is a type-checker and transpiler that supports type-checking React and JSX. -For more info, check out their guide on getting started with React and Webpack, or learn more about TypeScript's JSX support.

- -

To learn more about TypeScript in general, visit the TypeScript homepage.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/lifting-state-up.html b/docs/lifting-state-up.html new file mode 100644 index 0000000000..105a9c6577 --- /dev/null +++ b/docs/lifting-state-up.html @@ -0,0 +1,604 @@ + + + + + + + + + Lifting State Up - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Lifting State Up +

+
+ +

Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor. Let's see how this works in action.

+ +

In this section, we will create a temperature calculator that calculates whether the water would boil at a given temperature.

+ +

We will start with a component called BoilingVerdict. It accepts the celsius temperature as a prop, and prints whether it is enough to boil the water:

+
function BoilingVerdict(props) {
+  if (props.celsius >= 100) {
+    return <p>The water would boil.</p>;
+  } else {
+    return <p>The water would not boil.</p>;
+  }
+}
+
+

Next, we will create a component called Calculator. It renders an <input> that lets you enter the temperature, and keeps its value in this.state.value.

+ +

Additionally, it renders the BoilingVerdict for the current input value.

+
class Calculator extends React.Component {
+  constructor(props) {
+    super(props);
+    this.handleChange = this.handleChange.bind(this);
+    this.state = {value: ''};
+  }
+
+  handleChange(e) {
+    this.setState({value: e.target.value});
+  }
+
+  render() {
+    const value = this.state.value;
+    return (
+      <fieldset>
+        <legend>Enter temperature in Celsius:</legend>
+        <input
+          value={value}
+          onChange={this.handleChange} />
+        <BoilingVerdict
+          celsius={parseFloat(value)} />
+      </fieldset>
+    );
+  }
+}
+
+

Try it on CodePen.

+

Adding a Second Input #

+

Our new requirement is that, in addition to a Celsius input, we provide a Fahrenheit input, and they are kept in sync.

+ +

We can start by extracting a TemperatureInput component from Calculator. We will add a new scale prop to it that can either be "c" or "f":

+
const scaleNames = {
+  c: 'Celsius',
+  f: 'Fahrenheit'
+};
+
+class TemperatureInput extends React.Component {
+  constructor(props) {
+    super(props);
+    this.handleChange = this.handleChange.bind(this);
+    this.state = {value: ''};
+  }
+
+  handleChange(e) {
+    this.setState({value: e.target.value});
+  }
+
+  render() {
+    const value = this.state.value;
+    const scale = this.props.scale;
+    return (
+      <fieldset>
+        <legend>Enter temperature in {scaleNames[scale]}:</legend>
+        <input value={value}
+               onChange={this.handleChange} />
+      </fieldset>
+    );
+  }
+}
+
+

We can now change the Calculator to render two separate temperature inputs:

+
class Calculator extends React.Component {
+  render() {
+    return (
+      <div>
+        <TemperatureInput scale="c" />
+        <TemperatureInput scale="f" />
+      </div>
+    );
+  }
+}
+
+

Try it on CodePen.

+ +

We have two inputs now, but when you enter the temperature in one of them, the other doesn't update. This contradicts our requirement: we want to keep them in sync.

+ +

We also can't display the BoilingVerdict from Calculator. The Calculator doesn't know the current temperature because it is hidden inside the TemperatureInput.

+

Lifting State Up #

+

First, we will write two functions to convert from Celsius to Fahrenheit and back:

+
function toCelsius(fahrenheit) {
+  return (fahrenheit - 32) * 5 / 9;
+}
+
+function toFahrenheit(celsius) {
+  return (celsius * 9 / 5) + 32;
+}
+
+

These two functions convert numbers. We will write another function that takes a string value and a converter function as arguments and returns a string. We will use it to calculate the value of one input based on the other input.

+ +

It returns an empty string on an invalid value, and it keeps the output rounded to the third decimal place:

+
function tryConvert(value, convert) {
+  const input = parseFloat(value);
+  if (Number.isNaN(input)) {
+    return '';
+  }
+  const output = convert(input);
+  const rounded = Math.round(output * 1000) / 1000;
+  return rounded.toString();
+}
+
+

For example, tryConvert('abc', toCelsius) returns an empty string, and tryConvert('10.22', toFahrenheit) returns '50.396'.

+ +

Next, we will remove the state from TemperatureInput.

+ +

Instead, it will receive both value and the onChange handler by props:

+
class TemperatureInput extends React.Component {
+  constructor(props) {
+    super(props);
+    this.handleChange = this.handleChange.bind(this);
+  }
+
+  handleChange(e) {
+    this.props.onChange(e.target.value);
+  }
+
+  render() {
+    const value = this.props.value;
+    const scale = this.props.scale;
+    return (
+      <fieldset>
+        <legend>Enter temperature in {scaleNames[scale]}:</legend>
+        <input value={value}
+               onChange={this.handleChange} />
+      </fieldset>
+    );
+  }
+}
+
+

If several components need access to the same state, it is a sign that the state should be lifted up to their closest common ancestor instead. In our case, this is the Calculator. We will store the current value and scale in its state.

+ +

We could have stored the value of both inputs but it turns out to be unnecessary. It is enough to store the value of the most recently changed input, and the scale that it represents. We can then infer the value of the other input based on the current value and scale alone.

+ +

The inputs stay in sync because their values are computed from the same state:

+
class Calculator extends React.Component {
+  constructor(props) {
+    super(props);
+    this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
+    this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
+    this.state = {value: '', scale: 'c'};
+  }
+
+  handleCelsiusChange(value) {
+    this.setState({scale: 'c', value});
+  }
+
+  handleFahrenheitChange(value) {
+    this.setState({scale: 'f', value});
+  }
+
+  render() {
+    const scale = this.state.scale;
+    const value = this.state.value;
+    const celsius = scale === 'f' ? tryConvert(value, toCelsius) : value;
+    const fahrenheit = scale === 'c' ? tryConvert(value, toFahrenheit) : value;
+
+    return (
+      <div>
+        <TemperatureInput
+          scale="c"
+          value={celsius}
+          onChange={this.handleCelsiusChange} />
+        <TemperatureInput
+          scale="f"
+          value={fahrenheit}
+          onChange={this.handleFahrenheitChange} />
+        <BoilingVerdict
+          celsius={parseFloat(celsius)} />
+      </div>
+    );
+  }
+}
+
+

Try it on CodePen.

+ +

Now, no matter which input you edit, this.state.value and this.state.scale in the Calculator get updated. One of the inputs gets the value as is, so any user input is preserved, and the other input value is always recalculated based on it.

+

Lessons Learned #

+

There should be a single "source of truth" for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the top-down data flow.

+ +

Lifting state involves writing more "boilerplate" code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs. Since any state "lives" in some component and that component alone can change it, the surface area for bugs is greatly reduced. Additionally, you can implement any custom logic to reject or transform user input.

+ +

If something can be derived from either props or state, it probably shouldn't be in the state. For example, instead of storing both celsiusValue and fahrenheitValue, we store just the last edited value and its scale. The value of the other input can always be calculated from them in the render() method. This lets us clear or apply rounding to the other field without losing any precision in the user input.

+ +

When you see something wrong in the UI, you can use React Developer Tools to inspect the props and move up the tree until you find the component responsible for updating the state. This lets you trace the bugs to their source:

+ +

Monitoring State in React DevTools

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/lists-and-keys.html b/docs/lists-and-keys.html new file mode 100644 index 0000000000..12c3a0cf67 --- /dev/null +++ b/docs/lists-and-keys.html @@ -0,0 +1,640 @@ + + + + + + + + + Lists and Keys - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Lists and Keys +

+
+ +

First, let's review how you transform lists in JavaScript.

+ +

Given the code below, we use the map() function to take an array of numbers and double their values. We assign the new array returned by map() to the variable doubled and log it:

+
const numbers = [1, 2, 3, 4, 5];
+const doubled = numbers.map((number) => number * 2);
+console.log(doubled);
+
+

This code logs [2, 4, 6, 8, 10] to the console.

+ +

In React, transforming arrays into lists of elements is nearly identical.

+

Rendering Multiple Components #

+

You can build collections of elements and include them in JSX using curly braces {}.

+ +

Below, we loop through the numbers array using the Javascript map() function. We return an <li> element for each item. Finally, we assign the resulting array of elements to listItems:

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

We include the entire listItems array inside a <ul> element, and render it to the DOM:

+
ReactDOM.render(
+  <ul>{listItems}</ul>,
+  document.getElementById('root')
+);
+
+

Try it out on Codepen.

+ +

This code displays a bullet list of numbers between 1 and 5.

+

Basic List Component #

+

Usually you would render lists inside a component.

+ +

We can refactor the previous example into a component that accepts an array of numbers and outputs an unordered list of elements.

+
function NumberList(props) {
+  const numbers = props.numbers;
+  const listItems = numbers.map((number) =>
+    <li>{number}</li>
+  );
+  return (
+    <ul>{listItems}</ul>
+  );
+}
+
+const numbers = [1, 2, 3, 4, 5];
+ReactDOM.render(
+  <NumberList numbers={numbers} />,
+  document.getElementById('root')
+);
+
+

When you run this code, you'll be given a warning that a key should be provided for list items. A "key" is a special string attribute you need to include when creating lists of elements. We'll discuss why it's important in the next section.

+ +

Let's assign a key to our list items inside numbers.map() and fix the missing key issue.

+
function NumberList(props) {
+  const numbers = props.numbers;
+  const listItems = numbers.map((number) =>
+    <li key={number.toString()}>
+      {number}
+    </li>
+  );
+  return (
+    <ul>{listItems}</ul>
+  );
+}
+
+const numbers = [1, 2, 3, 4, 5];
+ReactDOM.render(
+  <NumberList numbers={numbers} />,
+  document.getElementById('root')
+);
+
+

Try it out on Codepen.

+

Keys #

+

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity:

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

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys:

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

When you don't have stable IDs for rendered items, you may use the item index as a key as a last resort:

+
const todoItems = todos.map((todo, index) =>
+  // Only do this if items have no stable IDs
+  <li key={index}>
+    {todo.text}
+  </li>
+);
+
+

We don't recommend using indexes for keys if the items can reorder, as that would be slow. You may read an in-depth explanation about why keys are necessary if you're interested.

+

Extracting Components with Keys #

+

Keys only make sense in the context of the surrounding array.

+ +

For example, if you extract a Number component, you should keep the key on the <Number /> elements in the array rather than on the root <li> element in the Number itself.

+ +

Example: Incorrect Key Usage

+
function Number(props) {
+  const value = props.value;
+  return (
+    // Wrong! There is no need to specify the key here:
+    <li key={value.toString()}>
+      {value}
+    </li>
+  );
+}
+
+function NumberList(props) {
+  const numbers = props.numbers;
+  const listItems = numbers.map((item) =>
+    // Wrong! The key should have been specified here:
+    <Number value={number} />
+  );
+  return (
+    <ul>
+      {listItems}
+    </ul>
+  );
+}
+
+const numbers = [1, 2, 3, 4, 5];
+ReactDOM.render(
+  <NumberList numbers={numbers} />,
+  document.getElementById('root')
+);
+
+

Example: Correct Key Usage

+
function Number(props) {
+  // Correct! There is no need to specify the key here:
+  return <li>{props.value}</li>;
+}
+
+function NumberList(props) {
+  const numbers = props.numbers;
+  const listItems = numbers.map((number) =>
+    // Correct! Key should be specified inside the array.
+    <Number key={number.toString()}
+            value={number} />
+  );
+  return (
+    <ul>
+      {listItems}
+    </ul>
+  );
+}
+
+const numbers = [1, 2, 3, 4, 5];
+ReactDOM.render(
+  <NumberList numbers={numbers} />,
+  document.getElementById('root')
+);
+
+

Try it out on Codepen.

+ +

A good rule of thumb is that elements inside the map() call need keys.

+

Keys Must Only Be Unique Among Siblings #

+

Keys used within arrays should be unique among their siblings. However they don't need to be globally unique. We can use the same keys when we produce two different arrays:

+
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.'}
+];
+ReactDOM.render(
+  <Blog posts={posts} />,
+  document.getElementById('root')
+);
+
+

Try it out on CodePen.

+ +

Keys serve as a hint to React but they don't get passed to your components. If you need the same value in your component, pass it explicitly as a prop with a different name:

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

With the example above, the Post component can read props.id, but not props.key.

+

Embedding map() in JSX #

+

In the examples above we declared a separate listItems variable and included it in JSX:

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

JSX allows embedding any expressions in curly braces so we could inline the map() result:

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

Try it out on CodePen.

+ +

Sometimes this results in clearer code, but this style can also be abused. Like in JavaScript, it is up to you to decide whether it is worth extracting a variable for readability. Keep in mind that if the map() body is too nested, it might be a good time to extract a component.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/more-about-refs-it-IT.html b/docs/more-about-refs-it-IT.html deleted file mode 100644 index 46734683c3..0000000000 --- a/docs/more-about-refs-it-IT.html +++ /dev/null @@ -1,603 +0,0 @@ - - - - - - - Riferimenti ai Componenti | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Riferimenti ai Componenti -

-
- -

Dopo aver costruito il tuo componente, potresti trovarti nella situazione di volere invocare dei metodi sulle istanze di componenti restituite da render(). Nella maggior parte dei casi, questo non è necessario poiché il flusso di dati reattivo assicura sempre che le proprietà più recenti siano assegnate a ciascun figlio prodotto da render(). Tuttavia, esistono dei casi in cui potrebbe essere necessario o desiderabile, quindi React fornisce una via d'uscita conosciuta come refs. Queste refs (riferimenti) sono particolarmente utili quando vuoi: trovare il markup DOM prodotto da un componente (ad esempio, per posizionarlo in modo assoluto), usare componenti React in una più ampia applicazione non-React, oppure effettuare la transizione del tuo codice a React.

- -

Vediamo come ottenere un ref, e quindi passiamo ad un esempio completo.

-

Il ref restituito da ReactDOM.render #

-

Da non confondersi con il metodo render() che definisci sul tuo componente (il quale restituisce un elemento DOM virtuale), ReactDOM.render() restituisce un riferimento all'istanza di supporto del tuo componente (o null per i componenti privi di stato).

-
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
-
-

Tieni a mente, tuttavia, che JSX non restituisce un'istanza di un componente! È solo un ReactElement: una rappresentazione leggera che istruisce React su come il componente montato debba apparire.

-
var myComponentElement = <MyComponent />; // Questo è un semplice ReactElement.
-
-// Qui va del codice...
-
-var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
-myComponentInstance.doSomething();
-
-
-

Nota:

- -

Questo deve essere usato soltanto al livello più alto. All'interno dei componenti, lascia che i tuoi props e state gestiscano la comunicazione con i componenti figli, oppure utilizza uno degli altri metodi per ottenere un ref (attributo stringa o callback).

-
-

L'Attributo ref Come Callback #

-

React supporta un attributo speciale che puoi assegnare a qualsiasi componente. L'attributo ref può essere una funzione callback, che sarà eseguita immediatamente dopo che il componente viene montato. Il componente referenziato sarà passato come parametro, e la funzione callback può utilizzare il componente immediatamente, oppure conservarne un riferimento per un uso successivo, o entrambe.

- -

È semplice come aggiungere un attributo ref a qualsiasi cosa restituita da render usando una funzione freccia di ES6:

-
  render: function() {
-    return (
-      <TextInput
-        ref={function(input) {
-          if (input != null) {
-            input.focus();
-          }
-        }} />
-    );
-  },
-
-

oppure usando una funzione freccia ES6:

-
  render: function() {
-    return <TextInput ref={(c) => this._input = c} />;
-  },
-  componentDidMount: function() {
-    this._input.focus();
-  },
-
-

Nota che quando il componente referenziato viene smontato e quando il valore di ref cambia, ref sarà chiamata con null come argomento. Ciò impedisce i memory leak nel caso in cui l'istanza venga conservata, come nel primo esempio. Nota che quando assegni il valore di ref a un'espressione di funzione in linea come negli esempi precedenti, React vede un oggetto funzione diverso ogni volta e pertanto in occasione di ciascun aggiornamento, ref verrà chiamata con null immediatamente prima di essere chiamata con l'istanza del componente.

- -

Puoi accedere al nodo DOM del componente direttamente chiamando ReactDOM.findDOMNode(argomentoDellaTuaCallback).

-

L'Attributo ref Come Stringa #

-

React supporta anche l'uso di una stringa (anziché una callback) come proprietà ref su qualsiasi componente, sebbene allo stato attuale questo approccio sia quasi esclusivamente superato.

- -
    -
  1. Assegna un attributo ref a qualsiasi cosa restituita da render come:

    -
    <input ref="myInput" />
    -
  2. -
  3. Altrove nel codice (tipicamente in un gestore di eventi), accedi all'istanza di supporto tramite this.refs come segue:

    -
    this.refs.myInput
    -
  4. -
- -

Puoi accedere direttamente al nodo DOM del componente chiamando ReactDOM.findDOMNode(this.refs.myInput).

-

Un Esempio Completo #

-

Per ottenere un riferimento a un componente React, puoi usare this per ottenere il componente React attuale, oppure usare un ref per ottenere un riferimento a un componente di tua proprietà. Il funzionamento è il seguente:

-
var MyComponent = React.createClass({
-  handleClick: function() {
-    // Assegna il focus esplicitamente al campo di testo usando l'API DOM nativa.
-    this.myTextInput.focus();
-  },
-  render: function() {
-    // L'attributo ref aggiunge un riferimento al componente a this.refs quando
-    // il componente viene montato
-    return (
-      <div>
-        <input type="text" ref={(ref) => this.myTextInput = ref} />
-        <input
-          type="button"
-          value="Assegna il focus al campo di testo"
-          onClick={this.handleClick}
-        />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <MyComponent />,
-  document.getElementById('example')
-);
-
-

In questo esempio, otteniamo un riferimento all'istanza di supporto del campo di testo e vi invochiamo il metodo focus() quando il bottone viene cliccato.

- -

Per componenti compositi, il riferimento si riferisce a un'istanza della classe del componente, quindi puoi invocare ogni metodo definito in tale classe. Se devi accedere al nodo DOM sottostante per il componente, puoi usare ReactDOM.findDOMNode.

-

Riassunto #

-

I riferimenti ref sono la maniera corretta di inviare un messaggio a una precisa istanza di un figlio in una maniera che sarebbe impraticabile attraverso le normali proprietà props e state di React. Tuttavia, esse non dovrebbero essere la tua astrazione principale per far fluire i dati attraverso la tua applicazione. In modo predefinito, usa il flusso dati di React e utilizza i ref per casi d'uso che sono intrinsecamente non reattivi.

-

Benefici: #

-
    -
  • Puoi definire ogni metodo pubblico nelle classi dei tuoi componenti (come un metodo per reimpostare un Typeahead) e chiamare tali metodi pubblici attraverso i riferimenti (come ad esempio this.refs.myTypeahead.reset()).
  • -
  • Effettuare misure sul DOM richiede quasi sempre l'accesso ad un componente "nativo" come <input /> accedendo il suo nodo DOM sottostante attraverso ReactDOM.findDOMNode(this.refs.myInput). I riferimenti sono uno degli unici metodi praticabili per fare ciò in maniera affidabile.
  • -
  • I riferimenti sono gestiti automaticamente per te! Se un figlio è distrutto, anche il suo riferimento è distrutto. Pertanto non preoccuparti del consumo di memoria (a meno che tu non faccia qualcosa di folle per conservare un riferimento).
  • -
-

Precauzioni: #

-
    -
  • Non accedere mai ai riferimenti dentro il metodo render di un componente - oppure mentre il metodo render di qualsiasi componente è in esecuzione ovunque nella pila di chiamate.
  • -
  • Se vuoi preservare la resilienza al Crushing del compilatore Google Closure Compiler, assicurati di non accedere mai come proprietà a ciò che è stato specificato come stringa. Ciò significa che devi accedere come this.refs['myRefString'] se il tuo ref è stato definito come ref="myRefString".
  • -
  • Se non hai ancora programmato parecchie applicazioni con React, la tua prima inclinazione è solitamente di provare a utilizzare i riferimenti per "fare succedere qualcosa" nella tua applicazione. Se questo è il tuo caso, fermati un momento e pensa in maniera critica al luogo corretto nella gerarchia dei componenti in cui lo state debba trovarsi. Spesso ti accorgerai che il luogo corretto per "possedere" lo stato si trova a un livello più alto nella gerarchia. Posizionare lì lo stato spesso elimina ogni necessità di usare i ref per "fare accadere qualcosa" – al contrario, il flusso dei dati solitamente otterrà lo scopo desiderato.
  • -
  • I ref non possono essere assegnati a funzioni prive di stato, poiché il componente non possiede un'istanza di supporto. Puoi tuttavia racchiudere un componente privo di stato in un componente composito standard e assegnare il ref al componente composito.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/more-about-refs-ja-JP.html b/docs/more-about-refs-ja-JP.html deleted file mode 100644 index b03c051d42..0000000000 --- a/docs/more-about-refs-ja-JP.html +++ /dev/null @@ -1,616 +0,0 @@ - - - - - - - 参照についての詳細 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 参照についての詳細 -

-
- -

renderメソッドからUIの構成をリターンした後、あなたは「リーチアウト」を見て、renderから返ってきたコンポーネントのインスタンスの上でメソッドを実行するでしょう。多くの場合、アプリケーションにおいて、データフローを作成することは必要ではありません。リアクティブなデータフローは常に最新の propsrender() から出力されたそれぞれの子要素に送られたことを保証するからです。しかし、まだ必要であったり、利益をもたらすケースもあります。

- -

'' という空の文字列でその値をアップデートした後にフォーカスするということを <input /> 要素(インスタンスのサブ階層に存在します)に伝えたいという場合を考えましょう。

-
  var App = React.createClass({
-    getInitialState: function() {
-      return {userInput: ''};
-    },
-    handleChange: function(e) {
-      this.setState({userInput: e.target.value});
-    },
-    clearAndFocusInput: function() {
-      this.setState({userInput: ''}); // inputをクリアします
-      // ここで、<input /> にフォーカスさせたいです!
-    },
-    render: function() {
-      return (
-        <div>
-          <div onClick={this.clearAndFocusInput}>
-            Click to Focus and Reset
-          </div>
-          <input
-            value={this.state.userInput}
-            onChange={this.handleChange}
-          />
-        </div>
-      );
-    }
-  });
-
-

この例では、どうにかしてinputに何かを「伝え」たいということに着目してください。何かというのは、propsから推測できるものではありません。このケースでは、inputが今フォーカスされるべきであるということを「伝え」たいのです。しかし、いくつか問題があります。render() で返されるものは実際の「子供の」要素ではありません。しかし、特別なインスタンスにおいて子要素の 説明 を行うよりかは、スナップショットを見ていったほうがいいでしょう。

- -
-

注意: -render() からリターンされるものは 実際に レンダリングされた子要素のインスタンスではないと覚えておいてください。 render() からリターンされるものは、ある特定の時点においてのコンポーネントの副階層にある単なる子要素のインスタンスの 説明 に過ぎません。

-
- -

これは、 render() からリターンされる何かを「保持し続ける」ことはできないことを意味します。そして、それは何かしら意味のあることであると予測できます。

-
  // 反例: このようには記述しないでください!
-  render: function() {
-    var myInput = <input />;          // このinputの上にあるメソッドを未来のいつかの
-    this.rememberThisInput = myInput; // タイミングで呼ぼうとしています!いえいっ!
-    return (
-      <div>
-        <div>...</div>
-        {myInput}
-      </div>
-    );
-  }
-
-

この反例では、 <input /> は単に <input />説明 に過ぎず、この説明は <input />現実の バッキングインスタンス を作るために使われます。

- -

では、inputの 現実の バッキングインスタンスについて、どのように話していきましょうか?

-

参照の文字列属性 #

-

Reactは render() からの出力であるコンポーネントであれば何でもアタッチできるとても特別なプロパティをサポートしています。この特別なプロパティは render() からのリターンである バッキングインスタンス に対応したものに参照することを許可します。これはどのタイミングにおいても、固有のインスタンスであることを保証されています。

- -

これは以下のように単純です。

- -
    -
  1. 以下のように、 render からのリターンであれば何でも ref 属性をアサインする。
  2. -
-
  <input ref="myInput" />
-
-
    -
  1. いくつかの他のコードは(一般的にイベントハンドラのコード)、以下にあるように this.refs を通して バッキングインスタンス にアクセスします。
  2. -
-
  this.refs.myInput
-
-

ReactDOM.findDOMNode(this.refs.myInput) を呼ぶことで、コンポーネントのDOMノードに直接アクセスできる。

-

参照のコールバック属性 #

-

ref 属性は名前の代わりのコールバック関数になり得ます。このコールバックはコンポーネントがマウントされた直後に実行されます。参照されたコンポーネントはパラメータとして渡され、コールバック関数はコンポーネントを即座に使用するか、または将来使用するために参照を保存します(またはその両方を行います)。

- -

これは、以下のように、 render でリターンされてきたものに ref 属性をアサインするのと同じくらい簡単です。

-
  <input ref={ function(component){ ReactDOM.findDOMNode(component).focus();} } />
-

完全な例 #

  var App = React.createClass({
-    getInitialState: function() {
-      return {userInput: ''};
-    },
-    handleChange: function(e) {
-      this.setState({userInput: e.target.value});
-    },
-    clearAndFocusInput: function() {
-      // inputをクリアする
-      this.setState({userInput: ''}, function() {
-        // このコードはコンポーネントが再度レンダリングされた後に実行されます。
-        ReactDOM.findDOMNode(this.refs.theInput).focus();   // どーん!フォーカスされました!
-      });
-    },
-    render: function() {
-      return (
-        <div>
-          <div onClick={this.clearAndFocusInput}>
-            Click to Focus and Reset
-          </div>
-          <input
-            ref="theInput"
-            value={this.state.userInput}
-            onChange={this.handleChange}
-          />
-        </div>
-      );
-    }
-  });
-
-

この例では、レンダリング関数は <input /> インスタンスの説明をリターンします。しかし、実際のインスタンスは this.refs.theInput を通してアクセスされます。 ref="theInput" を持つ子要素のコンポーネントが render からリターンされる限り、 this.refs.theInput は固有のインスタンスにアクセスするでしょう。これは <Typeahead ref="myTypeahead" /> のような高階層の(DOMでない)コンポーネントでも同様に動きます。

-

要約 #

-

リアクティブな propsstate を通してのストリーミングのアクセスは便利とは言えないため、参照は特定の子要素のインスタンスにメッセージを送るための素晴らしい方法です。しかし、それらは、アプリケーションを通したデータフローの抽象化につながるわけではありません。デフォルトで、リアクティブなデータフローを使ってください。そして、ユースケースのために ref を保存するのは本質的にはリアクティブではありません。

-

利益: #

-
    -
  • コンポーネントクラス(例えば、Typeaheadのリセットメソッドのようなもの)にパブリックなメソッドを定義できる。また、参照(例えば、 this.refs.myTypeahead.reset() のように)を通してそれらのパブリックなメソッドを呼べる。
  • -
  • DOMの計測を行うことは大体いつも <input /> のような「ネイティブの」コンポーネントや ReactDOM.findDOMNode(this.refs.myInput) を通した根本のDOMノードにアクセスすることを必要とします。参照は、こういったことを期待通りに行う唯一の実用的な方法です。
  • -
  • 参照は自動的に管理されます!もし子要素が削除されたら、その参照もまた削除されます。メモリに関しての心配は要りません(あなた自身が参照を維持するために何かおかしなことを行っていなければ)。
  • -
-

警告: #

-
    -
  • 決して コンポーネントのレンダリングメソッドの中の参照にアクセスしてはいけません。たとえコンポーネントのレンダリングメソッドのいずれかがコールスタックの中のどこかで動いているとしても。
  • -
  • もしGoogle Closure Compilerのクラッシュからの回復を守りたいなら、文字列として指定されたプロパティとしてアクセスしてはいけないことに気をつけてください。これは、 ref="myRefString" として参照が定義されている場合は、 this.refs['myRefString'] を使ってアクセスしなければいけないことを意味します。
  • -
  • まだReactでプログラムを書いたことがない場合は、アプリケーションで「何かを起こす」ために参照を使おうとするでしょう。もしそのケースだった場合は、時間をかけて state がコンポーネントの階層のどこで保持されるべきか批評的に考えてください。多くの場合は、そのstateを「保持する」ための固有の場所が階層の高いレベルにあることがクリアになります。そのstateをその場所に配置することはよく「何かを起こす」ために ref を使うための願望を排除します。代わりに、データフローは普通、目標を達成します。
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/more-about-refs-ko-KR.html b/docs/more-about-refs-ko-KR.html deleted file mode 100644 index afdc902f83..0000000000 --- a/docs/more-about-refs-ko-KR.html +++ /dev/null @@ -1,603 +0,0 @@ - - - - - - - refs에서 컴포넌트로 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- refs에서 컴포넌트로 -

-
- -

컴포넌트를 빌드한 후에는 render()에서 반환된 컴포넌트 인스턴스에 접근하거나 메소드를 호출할 방법이 필요할 수도 있습니다. 반응적 데이터 플로우가 render()의 결과물에서 최신의 props가 각각의 자식으로 보내진 것을 항상 보장하기 때문에 애플리케이션의 데이터 플로우를 만드는데 대체로 이런 작업은 필요가 없지만, 여전히 이런 작업이 필요하거나 유리한 경우가 있긴 합니다. React는 이를 위해 refs라는 탈출구를 제공합니다. refs(레퍼런스)는 특히 다음과 같은 경우 유용합니다: 컴포넌트에 의해 렌더된 DOM 마크업을 찾을때 (인스턴스내의 절대적인 위치), 큰 프로젝트의 일부에 React 컴포넌트를 사용하는 경우 또는 기존의 코드베이스를 React로 변경하는 경우.

- -

ref를 어떻게 얻는지 살펴보고, 예제를 완성해 봅시다.

-

ReactDOM.render에서 반환된 ref #

-

컴포넌트에서 정의한, 가상의 DOM 엘리먼트를 반환하는 render()와 헷갈리지 않도록 합니다. ReactDOM.render()는 컴포넌트의 지원 인스턴스(backing instance)에 대한 참조를 반환 합니다. 상태를 가지지 않는 컴포넌트에 대해선 null을 반환하죠.

-
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
-
-

명심하세요. 위의 코드는 컴포넌트 인스턴스를 반환하지 않습니다! 이는 그저 ReactElement:React에 마운트된 컴포넌트가 어떻게 보여야 할지 알려주는 경량의 표상(representation) 입니다.

-
var myComponentElement = <MyComponent />; // 이건 그냥 ReactElement 입니다.
-
-// 여기 코드가 위치합니다...
-
-var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
-myComponentInstance.doSomething();
-
-
-

주의:

- -

이는 오직 최상위 레벨에서만 사용되어야 합니다. 컴포넌트의 내부에서는 propsstate가 자식 컴포넌트와 통신하도록 하거나 문자열이나 콜백 어트리뷰트 등 ref를 얻어오는 다른 방법을 사용하도록 하세요.

-
-

ref 콜백 어트리뷰트 #

-

React는 어떤 컴포넌트에든 추가할 수 있는 특별한 어트리뷰트를 제공합니다. ref 어트리뷰트는 콜백 함수일 수 있으며 이는 컴포넌트가 마운트 된 후 즉시 실행됩니다. 참조된 컴포넌트는 파라미터로 전달될 것이며 콜백 함수는 즉시, 혹은 미래에 사용하기 위해 컴포넌트의 참조를 저장합니다.

- -

render에서 반환되는 무엇에든 ref 어트리뷰트를 추가하는 것은 간단합니다:

-
  render: function() {
-    return (
-      <TextInput
-        ref={function(input) {
-          if (input != null) {
-            input.focus();
-          }
-        }} />
-    );
-  },
-
-

ES6 화살표 함수를 사용한다면 다음과 같습니다:

-
  render: function() {
-    return <TextInput ref={(c) => this._input = c} />;
-  },
-  componentDidMount: function() {
-    this._input.focus();
-  },
-
-

<div /> 같은 DOM 컴포넌트에 ref를 추가하면 DOM 노드를 얻게 됩니다; <TextInput /> 같은 합성 컴포넌트에 ref를 추가하면 React 클래스 인스턴스를 얻게 됩니다. 후자의 경우, 클래스에 정의되어 있는 노출된 메소드를 호출할 수 있습니다.

- -

참조된 컴포넌트가 언마운트되고 ref가 변경되면 이전의 ref는 null을 인수로 호출됨을 주의 하세요. 이는 첫번째 예제에서처럼 인스턴트가 저장된 경우의 메모리 누수를 방지합니다. 또한 예제와 같이 ref를 인라인 함수 표현식으로 서술하게되면 React는 모든 업데이트에 대해 다른 함수 객체를 참조하게 됩니다. ref는 컴포넌트의 인스턴스의 호출 이전에 null 객체와 함께 즉시 호출될 것입니다.

-

ref 문자열 어트리뷰트 #

-

React는 ref에 콜백 대신 문자열도 지원합니다 이런 접근은 이제 과거의 것이긴 합니다.

- -
    -
  1. render에서 반환된 값을 ref 어트리뷰트에 할당합니다:

    -
    <input ref="myInput" />
    -
  2. -
  3. 다른 코드(일반적으로는 이벤트 핸들러 코드)에서 this.refs를 통해 지원 인스턴스에 접근 합니다:

    -
    var input = this.refs.myInput;
    -var inputValue = input.value;
    -var inputRect = input.getBoundingClientRect();
    -
  4. -
-

최종 예제 #

-

React 컴포넌트의 참조를 얻기 위해서, 현재의 React 컴포넌트를 위해서는 this를, 소유한 컴포넌트에 대해서는 ref를 사용할 수 있습니다. 다음과 같이 작동 합니다:

-
var MyComponent = React.createClass({
-  handleClick: function() {
-    // 명시적으로 텍스트 인풋에 포커스하기 위해 raw DOM API를 사용합니다.
-    this.myTextInput.focus();
-  },
-  render: function() {
-    // ref 어트리뷰트는 컴포넌트가 마운트되면
-    // this.refs에 컴포넌트에 대한 참조를 추가합니다.
-    return (
-      <div>
-        <input type="text" ref={(ref) => this.myTextInput = ref} />
-        <input
-          type="button"
-          value="Focus the text input"
-          onClick={this.handleClick}
-        />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <MyComponent />,
-  document.getElementById('example')
-);
-
-

이 예제에서, 텍스트 인풋의 지원 인스턴스에 대한 참조를 얻었으며 버튼이 클릭되었을때 focus()를 호출했습니다.

- -

합성 컴포넌트에서는 참조는 컴포넌트 클래스의 인스턴스를 가리키기 때문에 클래스에 정의된 어떤 메소드도 호출할 수 있습니다. 컴포넌트의 기저에 있는 DOM 노드에 접근하기 위해서는 ReactDOM.findDOMNode를 "탈출구"로 사용할 수 있습니다. 하지만 이는 캡슐화를 깨며, 대부분의 경우 React 모델을 이용해 더 명확한 방법으로 구조를 짤 수 있기 때문에 추천하지 않습니다.

-

요약 #

-

Refs는 반응적인 propsstate 스트리밍을 통해서는 불편했던 특정한 자식 인스턴스에 메시지 보내기를 수행하는 좋은 방법입니다. 하지만 애플리케이션의 데이터 플로우 전반에 사용해도 되는 go-to 같은 개념은 아닙니다. 기본적으로는 반응적인 데이터 플로우를 사용하고, ref는 근본적으로 반응적이지 않은 경우에만 사용하세요.

-

이점: #

-
    -
  • 컴포넌트 클래스에 public 메소드(ex. Typeahead의 reset)를 선언할 수 있으며 refs를 통해 그를 호출할 수 있습니다. (ex. this.refs.myTypeahead.reset()) 대부분, 이는 선언적으로 refs를 사용하는 것보다 내장 React 데이터 흐름을 명확하게 합니다.
  • -
  • DOM을 측정하기 위해서는 거의 항상 <input /> 같은 "기본" 컴포넌트를 다루고 ref를 통해 그 기저의 DOM 노드에 접근해야 합니다. Refs는 이 일을 확실하게 수행하는 몇 안 되는 실용적인 방법의 하나입니다.
  • -
  • Refs는 자동으로 관리합니다! 자식이 파괴되면, 그의 ref도 마찬가지로 파괴됩니다. 참조를 유지하기 위해 뭔가 미친 짓을 하지 않는 한, 메모리 걱정은 하지 않아도 됩니다.
  • -
-

주의: #

-
    -
  • 컴포넌트의 렌더 메소드에서는, 혹은 컴포넌트의 렌더 메소드가 콜스택 어디에서든 실행되는 동안에는 절대 접근하지 마세요.
  • -
  • Google Closure Compiler에서의 어드벤스드 모드 분쇄 복원력 유지(to preserve advanced-mode crushing resilience)를 위해서는 문자열로 정의한 것을 절대 프로퍼티로 접근하지 마세요. ref가 ref="myRefString"으로 정의되어 있다면 this.refs['myRefString']으로만 접근해야 한다는 이야기 입니다.
  • -
  • React로 앱을 여럿 만들어 본 경험이 없다면, 보통은 처음엔 앱에서 "무언가 일어나도록" 하는데 refs를 사용하게 될 것입니다. 이 경우, 잠시 시간을 내어 state가 컴포넌트 계층구조의 어느 부분에서 관리되어야 할지 비판적으로 생각해 봅시다. 대개는 state가 계층구조의 더 높은 레벨에서 "소유"하는 것이 타당함이 명확해집니다. 그렇게 함으로써 ref를 사용해 "무언가 일어나도록" 하려는 욕망이 대부분 제거됩니다. - 대신에 데이터 플로우를 통해 대개 원하는 바를 달성하게 될 것입니다.
  • -
  • Refs는 상태를 가지지 않는 함수에 붙일 수 없습니다. 왜냐하면 컴포넌트가 내부 인스턴스를 가지지 않기 때문입니다. 상태를 가지지 않는 컴포넌트는 항상 일반 컴포넌트로 감싸 ref를 조합 컴포넌트에 붙일 수 있습니다.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/more-about-refs-zh-CN.html b/docs/more-about-refs-zh-CN.html deleted file mode 100644 index 7244e0726c..0000000000 --- a/docs/more-about-refs-zh-CN.html +++ /dev/null @@ -1,603 +0,0 @@ - - - - - - - 对组件的refs | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 对组件的refs -

-
- -

在建立你的组件以后,你也许发现你想“接触”并且调用从 render()返回的组件实例上的方法。大部分情况下,这是不必要的因为响应式的数据流总是确保最近的 props 被送到每一个从 render() 输出的子级。然而,有一些情况下它仍旧是必要或者有益的,所以 React 提供了一个被称为 refs 的安全舱口。这些 refs (引用) 在你需要时特别有用 如:查找被组件绘制的 DOM 标记(例如,绝对定位它),使用 React 组件在一个大的非React组件里,或者转换你已有的代码库到React。

- -

让我们来看看怎样取得一个ref,然后深入完整的例子。

-

从 ReactDOM.render 返回的 ref #

-

不要被你在你的组件(它返回一个虚拟的DOM元素)里定义的 render() 迷惑了, ReactDOM.render() 会返回一个对你的组件的 backing instance 的引用(无状态组件 返回 null).

-
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
-
-

记住,不管怎样,JSX不会返回一个组件的实例!它只是一个 ReactElement: 一个轻量级的表达,告诉React被挂载的组件应该长什么样。

-
var myComponentElement = <MyComponent />; // 这只是一个 ReactElement.
-
-// 省略一些代码 ...
-
-var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
-myComponentInstance.doSomething();
-
-
-

注意:

- -

这只应该用在顶层上。在组件内部,让你的 propsstate 来处理和子组件的通信,或者使用其他获取ref的方法(string attribute or callbacks)。

-
-

ref Callback 属性 #

-

React支持一种非常特殊的属性,你可以附加到任何的组件上。 ref 属性可以是一个回调函数,这个回调函数会在组件被挂载后立即执行。被引用的组件会被作为参数传递,回调函数可以用立即使用这个组件,或者保存引用以后使用(或者二者皆是)。

- -

简单的说就是添加一个 ref 属性到任何从 render 返回的东西上:

-
  render: function() {
-    return (
-      <TextInput
-        ref={function(input) {
-          if (input != null) {
-            input.focus();
-          }
-        }} />
-    );
-  },
-
-

或者使用ES6的箭头函数:

-
  render: function() {
-    return <TextInput ref={(c) => this._input = c} />;
-  },
-  componentDidMount: function() {
-    this._input.focus();
-  },
-
-

当连接一个ref到一个DOM组件如 <div />,你取回DOM节点;当连接一个ref到一个复合组件如 <TextInput />,你会得到React类的实例。在后一种情况下,你可以调用任何那个组件的类暴露的方法。

- -

注意当被引用的组件卸载和每当ref变动,旧的ref将会被以null做参数调用。这阻止了在实例被保存的情况下的内存泄露,如第二个例子。注意当像在这里的例子,使用内联函数表达式写refs,React在每次更新都看到不同的函数对象,ref将会被以null 立即调用在它被以组件实例调用前。

-

ref String 属性 #

-

React同样支持使用一个字符串(代替回调函数)在任意组件上作为一个 ref prop,尽管这个方法在这点上主要是遗留物。

- -
    -
  1. 赋值ref属性为任何从render 返回的东西,比如:

    -
    <input ref="myInput" />
    -
  2. -
  3. 在其他一些代码中(典型的如事件处理的代码),通过this.refs访问 支持实例(backing instance),如:

    -
    var input = this.refs.myInput;
    -var inputValue = input.value;
    -var inputRect = input.getBoundingClientRect();
    -
  4. -
-

完整的示例 #

-

为了获取一个React组件的引用,你既可以使用 this 来获取当前的React组件,也可以使用一个 ref 来获取一个你拥有的组件的引用。他们像这样工作:

-
var MyComponent = React.createClass({
-  handleClick: function() {
-    // Explicitly focus the text input using the raw DOM API.
-    this.myTextInput.focus();
-  },
-  render: function() {
-    // The ref attribute adds a reference to the component to
-    // this.refs when the component is mounted.
-    return (
-      <div>
-        <input type="text" ref={(ref) => this.myTextInput = ref} />
-        <input
-          type="button"
-          value="Focus the text input"
-          onClick={this.handleClick}
-        />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <MyComponent />,
-  document.getElementById('example')
-);
-
-

在这个例子中,我们获得一个对 text input backing instance 的引用 并且当按钮被点击时我们调用 focus()

- -

对于复合组件,引用会指向一个组件类的实例所以你可以调用那个类定义的任何方法。如果你需要访问那个组件的底层的DOM节点,你可以使用 ReactDOM.findDOMNode 作为一个 安全舱口 但是我们不推荐这样,因为它打破了封装,在大多数情况下都有一个清晰的方法来以React模式构建你的代码.

-

总结 #

-

Refs是一种很好的发送消息给特定子实例(通过流式的Reactive propsstate来做会不方便)的方式。它们应该,不论怎样,不是你的应用中数据流通的首选。默认情况下,使用响应式数据流,并为本身不是reactive的用例保存ref

-

优点: #

-
    -
  • 你可以在你的组件类里定义任何的公开方法(比如在一个Typeahead的重置方法)然后通过refs调用那些公开方法(比如this.refs.myTypeahead.reset())。在大多数情况下,使用内建的React数据流更清晰,而不是使用强制的ref。
  • -
  • 实行DOM测量几乎总是需要接触到 "原生" 组件比如 <input /> 并且通过 ref 访问它的底层DOM节点。 Refs 是唯一一个可靠的完成这件事的实际方式。
  • -
  • Refs 是为你自动管理的!如果子级被销毁了,它的ref也同样为你销毁了。这里不用担心内存(除非你做了一些疯狂的事情来自己保持一份引用)。
  • -
-

注意事项: #

-
    -
  • 绝不 在任何组件的 render 方法中访问 refs - 或者当任何组件的render方法还在调用栈上的任何地方运行时。
  • -
  • 如果你想要保留Google Closure Compiler advanced-mode crushing resilience,务必不要以属性的方式访问指明为字符串的属性。这意味这你必须用this.refs['myRefString']访问,如果你的ref被定义为ref="myRefString"
  • -
  • 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考state应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里 往往消除了任何使用refs 来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目标。
  • -
  • Refs 不能连接到一个 stateless function(无状态函数),因为这些组件没有支持实例。你总是可以包装一个无状态组件在一个标准复合组件里并且连接一个ref到这个复合组件。
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/more-about-refs.html b/docs/more-about-refs.html deleted file mode 100644 index 7e96d23571..0000000000 --- a/docs/more-about-refs.html +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - - Refs to Components | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Refs to Components -

-
- -

After building your component, you may find yourself wanting to "reach out" and invoke methods on component instances returned from render(). In most cases, this should be unnecessary because the reactive data flow always ensures that the most recent props are sent to each child that is output from render(). However, there are a few cases where it still might be necessary or beneficial, so React provides an escape hatch known as refs. These refs (references) are especially useful when you need to find the DOM markup rendered by a component (for instance, to position it absolutely), use React components in a larger non-React application, or transition your existing codebase to React.

- -

Let's look at how to get a ref, and then dive into a complete example.

-

The ref returned from ReactDOM.render #

-

Not to be confused with the render() function that you define on your component (and which returns a virtual DOM element), ReactDOM.render() will return a reference to your component's backing instance (or null for stateless components).

-
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
-
-

Keep in mind, however, that the JSX doesn't return a component instance! It's just a ReactElement: a lightweight representation that tells React what the mounted component should look like.

-
var myComponentElement = <MyComponent />; // This is just a ReactElement.
-
-// Some code here...
-
-var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
-myComponentInstance.doSomething();
-
-
-

Note:

- -

This should only ever be used at the top level. Inside components, let your props and state handle communication with child components, or use one of the other methods of getting a ref (string attribute or callbacks).

-
-

The ref Callback Attribute #

-

React supports a special attribute that you can attach to any component. The ref attribute can be a callback function, and this callback will be executed immediately after the component is mounted. The referenced component will be passed in as a parameter, and the callback function may use the component immediately, or save the reference for future use (or both).

- -

It's as simple as adding a ref attribute to anything returned from render:

-
  render: function() {
-    return (
-      <TextInput
-        ref={function(input) {
-          if (input != null) {
-            input.focus();
-          }
-        }} />
-    );
-  },
-
-

or using an ES6 arrow function:

-
  render: function() {
-    return <TextInput ref={(c) => this._input = c} />;
-  },
-  componentDidMount: function() {
-    this._input.focus();
-  },
-
-

When attaching a ref to a DOM component like <div />, you get the DOM node back; when attaching a ref to a composite component like <TextInput />, you'll get the React class instance. In the latter case, you can call methods on that component if any are exposed in its class definition.

- -

Note that when the referenced component is unmounted and whenever the ref changes, the old ref will be called with null as an argument. This prevents memory leaks in the case that the instance is stored, as in the second example. Also note that when writing refs with inline function expressions as in the examples here, React sees a different function object each time so on every update, ref will be called with null immediately before it's called with the component instance.

-

The ref String Attribute #

-
-

Note:

- -

Although string refs are not deprecated, they are considered legacy, and will likely be deprecated at some point in the future. Callback refs are preferred.

-
- -

React also supports using a string (instead of a callback) as a ref prop on any component.

- -
    -
  1. Assign a ref attribute to anything returned from render such as:

    -
    <input ref="myInput" />
    -
  2. -
  3. In some other code (typically event handler code), access the backing instance via this.refs as in:

    -
    var input = this.refs.myInput;
    -var inputValue = input.value;
    -var inputRect = input.getBoundingClientRect();
    -
  4. -
-

A Complete Example #

-

In order to get a reference to a React component, you can either use this to get the current React component, or you can use a ref to get a reference to a component you own. They work like this:

-
var MyComponent = React.createClass({
-  handleClick: function() {
-    // Explicitly focus the text input using the raw DOM API.
-    if (this.myTextInput !== null) {
-      this.myTextInput.focus();
-    }
-  },
-  render: function() {
-    // The ref attribute is a callback that saves a reference to the
-    // component to this.myTextInput when the component is mounted.
-    return (
-      <div>
-        <input type="text" ref={(ref) => this.myTextInput = ref} />
-        <input
-          type="button"
-          value="Focus the text input"
-          onClick={this.handleClick}
-        />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <MyComponent />,
-  document.getElementById('example')
-);
-
-

In this example, we get a reference to the text input backing instance and we call focus() when the button is clicked.

- -

For composite components, the reference will refer to an instance of the component class so you can invoke any methods that are defined on that class. If you need access to the underlying DOM node for that component, you can use ReactDOM.findDOMNode as an "escape hatch" but we don't recommend it since it breaks encapsulation and in almost every case there's a clearer way to structure your code within the React model.

-

Summary #

-

Refs are a great way to send a message to a particular child instance in a way that would be inconvenient to do via streaming Reactive props and state. They should, however, not be your go-to abstraction for flowing data through your application. By default, use the Reactive data flow and save refs for use cases that are inherently non-reactive.

-

Benefits: #

-
    -
  • You can define any public method on your component classes (such as a reset method on a Typeahead) and call those public methods through refs (such as this.refs.myTypeahead.reset()). In most cases, it's clearer to use the built-in React data flow instead of using refs imperatively.
  • -
  • Performing DOM measurements almost always requires reaching out to a "native" component such as <input /> and accessing its underlying DOM node using a ref. Refs are one of the only practical ways of doing this reliably.
  • -
  • Refs are automatically managed for you! If that child is destroyed, its ref is also destroyed for you. No worrying about memory here (unless you do something crazy to retain a reference yourself).
  • -
-

Cautions: #

-
    -
  • Never access refs inside of any component's render method – or while any component's render method is even running anywhere in the call stack.
  • -
  • If you want to preserve Google Closure Compiler advanced-mode crushing resilience, make sure to never access as a property that was specified as a string. This means you must access using this.refs['myRefString'] if your ref was defined as ref="myRefString".
  • -
  • If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use refs to "make things happen" – instead, the data flow will usually accomplish your goal.
  • -
  • Refs may not be attached to a stateless function, because the component does not have a backing instance. You can always wrap a stateless component in a standard composite component and attach a ref to the composite component.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/multiple-components-it-IT.html b/docs/multiple-components-it-IT.html deleted file mode 100644 index b6c358ead1..0000000000 --- a/docs/multiple-components-it-IT.html +++ /dev/null @@ -1,636 +0,0 @@ - - - - - - - Componenti Multipli | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Componenti Multipli -

-
- -

Finora abbiamo visto come scrivere un singolo componente per mostrare dati e gestire l'input dell'itente. Adesso esaminiamo una delle migliori caratteristiche di React: la componibilità.

-

Motivazione: Separazione dei Concetti #

-

Costruendo componenti modulari che riutilizzano altri componenti con interfacce ben definite, ottieni gli stessi benefici che otterresti usando funzioni o classi. Nello specifico, puoi separare i diversi concetti della tua applicazione nel modo che preferisci semplicemente costruendo nuovi componenti. Costruendo una libreria di componenti personalizzati per la tua applicazione, stai esprimendo la tua UI in una maniera che si adatta meglio al tuo dominio.

-

Esepmio di Composizione #

-

Creiamo un semplice componente Avatar che mostra una foto del profilo e un nome utente usando la Graph API di Facebook.

-
var Avatar = React.createClass({
-  render: function() {
-    return (
-      <div>
-        <ProfilePic username={this.props.username} />
-        <ProfileLink username={this.props.username} />
-      </div>
-    );
-  }
-});
-
-var ProfilePic = React.createClass({
-  render: function() {
-    return (
-      <img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
-    );
-  }
-});
-
-var ProfileLink = React.createClass({
-  render: function() {
-    return (
-      <a href={'https://www.facebook.com/' + this.props.username}>
-        {this.props.username}
-      </a>
-    );
-  }
-});
-
-ReactDOM.render(
-  <Avatar username="pwh" />,
-  document.getElementById('example')
-);
-

Possesso #

-

Nell'esempio precedente, le istanze di Avatar posseggono instanze di ProfilePic e ProfileLink. In React, un proprietario è il componente che imposta le props di altri componenti. Più formalmente, se un componente X è creato nel metodo render() del componente Y, si dice che X è di proprietà di Y. Come discusso in precedenza, un componente non può mutare le sue props — sono sempre consistenti con il valore che il suo proprietario ha impostato. Questa invariante fondamentale porta a UI la cui consistenza può essere garantita.

- -

È importante distinguere tra la relazione di proprietario-proprietà e la relazione genitore-figlio. La relazione proprietario-proprietà è specifica di React, mentre la relazione genitore-figlio è semplicemente quella che conosci e ami del DOM. Nell'esempio precedente, Avatar possiede il div, le istanze di ProfilePic e ProfileLink, e div è il genitore (ma non il proprietario) delle istanze di ProfilePic e ProfileLink.

-

Figli #

-

Quando crei un'istanza di un componente React, puoi includere componenti React aggiuntivi o espressioni JavaScript tra i tag di apertura e chiusura come segue:

-
<Parent><Child /></Parent>
-
-

Parent può accedere ai propri figli leggendo la speciale proprietà this.props.children. this.props.children è una struttura dati opaca: usa le utilità React.Children per manipolare i figli.

-

Riconciliazione dei Figli #

-

La riconciliazione è il processo per il quale React aggiorna il DOM ad ogni passata di rendering. In generale, i figli sono riconciliati secondo l'ordine in cui sono mostrati. Per esempio, supponiamo che due passate di rendering generino rispettivamente il markup seguente:

-
// Prima passata di rendering
-<Card>
-  <p>Paragrafo 1</p>
-  <p>Paragrafo 2</p>
-</Card>
-// Seconda passata di rendering
-<Card>
-  <p>Paragrafo 2</p>
-</Card>
-
-

Intuitivamente, <p>Paragrafo 1</p> è stato rimosso. Invece, React riconcilierà il DOM cambiando il testo contenuto nel primo figlio e distruggerà l'ultimo figlio. React reconcilia secondo l'ordine dei figli.

-

Figli Dotati di Stato #

-

Per molti componenti, questo non è un grande problema. Tuttavia, per i componenti dotati di stato che mantengono dati in this.state attraverso le diverse passate di rendering, questo può essere problematico.

- -

In molti casi, questo problema può essere aggirato nascondendo gli elementi anziché distruggendoli:

-
// Prima passata di rendering
-<Card>
-  <p>Paragrafo 1</p>
-  <p>Paragrafo 2</p>
-</Card>
-// Seconda passata di rendering
-<Card>
-  <p style={{display: 'none'}}>Paragrafo 1</p>
-  <p>Paragrafo 2</p>
-</Card>
-

Figli Dinamici #

-

La situazione si complica quando i figli sono rimescolati (come nei risultati della ricerca) o se nuovi componenti sono aggiunti all'inizio della lista (come negli stream). In questi casi quando l'identità e lo stato di ogni figlio deve essere preservato attraverso passate di rendering, puoi unicamente identificare ciascun figlio assegnandogli una proprietà key:

-
  render: function() {
-    var results = this.props.results;
-    return (
-      <ol>
-        {results.map(function(result) {
-          return <li key={result.id}>{result.text}</li>;
-        })}
-      </ol>
-    );
-  }
-
-

Quando React riconcilia i figli dotati di key, si assicurerà che ciascun figlio con la proprietà key sia riordinato (anziché clobbered) o distrutto (anziché riutilizzato).

- -

La proprietà key dovrebbe sempre essere fornita direttamente all'elemento del componente nell'array, non al contenitore HTML di ciascun componente dell'array:

-
// SBAGLIATO!
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li key={this.props.data.id}>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-          return <ListItemWrapper data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
// Corretto :)
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-           return <ListItemWrapper key={result.id} data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
-

Puoi anche assegnare chiavi ai figli passandogli un oggetto ReactFragment. Leggi Frammenti con Chiave per maggiori dettagli.

-

Flusso dei Dati #

-

In React, i dati fluiscono dal proprietario al componente posseduto attraverso le props come discusso in precedenza. Questo è a tutti gli effetti un binding di dati unidirezionale: i proprietari legano le proprietà dei componenti di loro proprietà a dei valori che il proprietario stesso ha calcolato in base ai propri props o state. Dal momento che questo processo avviene ricorsivamente, i cambiamenti dei dati vengono riflessi automaticamente ovunque vengano usati.

-

Una Nota sulle Prestazioni #

-

Ti starai chiedendo che cambiare i dati sia un'operazione costosa in presenza di un gran numero di nodi sotto un proprietario. La buona notizia è che JavaScript è veloce e i metodi render() tendono ad essere molto semplici, quindi in molte applicazioni questo è un processo estremamente veloce. Inoltre, il collo di bottiglia è quasi sempre la mutazione del DOM e non l'esecuzione di JS. React ottimizzerà tutto per te usando il raggruppamento e osservando i cambiamenti.

- -

Tuttavia, a volte vorrai avere un controllo più raffinato sulle tue prestazioni. In tal caso, ridefinisci il metodo shouldComponentUpdate() per restituire false quando vuoi che React salti il trattamento di un sottoalbero. Consulta la documentazione di riferimento di React per maggiori informazioni.

- -
-

Nota:

- -

Se shouldComponentUpdate() restituisce false quando i dati sono effettivamente cambiati, React non è in grado di mantenere la tua UI in sincronia. Assicurati di usare questa tecnica con cognizione di causa, e soltanto in presenza di problemi percettibili di prestazioni. Non sottovalutare l'estrema velocità di esecuzione di JavaScript se paragonata a quella del DOM.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/multiple-components-ja-JP.html b/docs/multiple-components-ja-JP.html deleted file mode 100644 index 58643b852c..0000000000 --- a/docs/multiple-components-ja-JP.html +++ /dev/null @@ -1,636 +0,0 @@ - - - - - - - 複数のコンポーネント | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 複数のコンポーネント -

-
- -

今まで、データを表示したりユーザの入力をハンドルするための1つのコンポーネントの書き方を見てきました。次に、 Reactの最も面白い特徴であるコンポーザビリティについて見ていきましょう。

-

動機: 関心の分離 #

-

うまく定義されたインターフェースとともに他のコンポーネントを再利用するモジュールのコンポーネントを構築することによって、関数やクラスを使う場合と同じ利益を得ることができます。特に、アプリの 異なった関心を分離 できるにも関わらず、新しいコンポーネントを単純に構築することで満足する場合には。アプリケーションにカスタムコンポーネントライブラリを構築することによって、あなたがやりたいことに最も合う方法でUIを表現することができます。

-

構成例 #

-

FacebookのグラフAPIを使って、プロフィール画像とユーザー名を表示する単純なアバターのコンポーネントを作ってみましょう。

-
var Avatar = React.createClass({
-  render: function() {
-    return (
-      <div>
-        <ProfilePic username={this.props.username} />
-        <ProfileLink username={this.props.username} />
-      </div>
-    );
-  }
-});
-
-var ProfilePic = React.createClass({
-  render: function() {
-    return (
-      <img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
-    );
-  }
-});
-
-var ProfileLink = React.createClass({
-  render: function() {
-    return (
-      <a href={'https://www.facebook.com/' + this.props.username}>
-        {this.props.username}
-      </a>
-    );
-  }
-});
-
-ReactDOM.render(
-  <Avatar username="pwh" />,
-  document.getElementById('example')
-);
-

所有 #

-

上記の例では、 Avatar のインスタンスは ProfilePicProfileLink のインスタンスを 所有 しています。Reactでは、 所有者は、他のコンポーネントの props をセットするコンポーネントです。 正式に言うと、もし Y コンポーネントの render() メソッドの中に X コンポーネントが作られた場合、 XY に所有されていると言います。以前述べたように、コンポーネントはそれ自身の props を変化させることはできません。 props は常に、所有者が彼らにセットしたものと一貫性があります。このキー要素は一貫性があることを保証するために、UIに反映されます。

- -

所有者と所有される側の関係と、親子の関係の違いを示すのは重要です。所有者と所有される側の関係はReact独特です。一方で、親子の関係は単純にDOMから分かる、愛すべき関係です。上の例では、 Avatardiv を所有しますが、 ProfilePicProfileLink インスタンスと、 divProfilePicProfileLinkインスタンスの (しかし、所有者ではありません)です。

-

#

-

Reactのコンポーネントのインスタンスを作成する時には、以下のように開始タグと終了タグの間に付加的なReactのコンポーネントやJavaScriptの表現を含めることができます。

-
<Parent><Child /></Parent>
-
-

Parent は特別な this.props.children というプロパティでアクセスすることで、子要素を読み取ることができます。 this.props.children は不透明なデータ構造です。 操作するにはReact.Children utilitiesを使用してください。

-

子要素の調和 #

-

調和はReactが新しいレンダリングのパスごとにDOMをアップデートするプロセスです。 一般的に、子要素はレンダリングされる順序に従って調和します。例えば、2つのレンダリングパスを考えると、以下のそれぞれのマークアップが生成されます。

-
// パス1のレンダリング
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// パス2のレンダリング
-<Card>
-  <p>Paragraph 2</p>
-</Card>
-
-

直感的には、 <p>Paragraph 1</p> が削除されたように思えます。代わりに、Reactは1つ目の子要素のテキストコンテンツを変更し、最後の子要素を削除するという変更を加えることでDOMを調和させます。Reactは子要素の 順序 に従って調和するのです。

-

ステートフルな子要素 #

-

多くのコンポーネントにとって、これは大きな処理ではありません。しかし、レンダリングのパスを超えて、 this.state にデータを保持しているステートフルなコンポーネントにとっては、これはとても問題になり得ます。

- -

多くのケースにおいては、以下のように、削除する代わりに要素を隠すことで回避することがあります。

-
// パス1のレンダリング
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// パス2のレンダリング
-<Card>
-  <p style={{display: 'none'}}>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-

動的な子要素 #

-

子要素がシャッフルされているような時(検索結果のように)や、リストの最初に新しいコンポーネントが追加されるような時(ストリームのように)には、状況はさらに複雑になります。そういったケースでは、それぞれの子要素のアイデンティティやstateがレンダリングパスを保持する必要があり、以下のように key を認識することでそれぞれの子要素をただ1つに識別できます。

-
  render: function() {
-    var results = this.props.results;
-    return (
-      <ol>
-        {results.map(function(result) {
-          return <li key={result.id}>{result.text}</li>;
-        })}
-      </ol>
-    );
-  }
-
-

Reactがキー付けされた子要素を調和させるとき、 key と子要素が再び整理される(けんかをする代わりに)か削除されます(再利用される代わりに)。

- -

key は以下のように 常に 配列の中でコンポーネントに直接提供されるべきで、その配列の中でそれぞれのコンポーネントのHTMLの子要素の入れ物に提供されるべきではありません。

-
// 間違い!
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li key={this.props.data.id}>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-          return <ListItemWrapper data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
-// 正解 :)
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-           return <ListItemWrapper key={result.id} data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
-

Reactのフラグのオブジェクトを渡すことで子要素をキー付けすることもできます。詳細は、キー付けされたフラグをご覧ください。

-

データフロー #

-

Reactの、 props を通した所有者から所有されるコンポーネントへのデータフローは今までに記述してきました。これは実際には一方向のデータバインディングです。所有者は所有しているコンポーネントのpropsを、所有者が propsstate に基づいて計算したいくつかの値にバインドします。このプロセスが何度も行われるので、データの変更は彼らが使われるところは自動的にどこでも反映されます。

-

パフォーマンスの注意 #

-

みなさんは所有者の下にたくさんのノードがあるときには、データの変更には多くのコストがかかると考えるでしょう。良いニュースとして、JavaScriptは早く、 render() メソッドはとても単純になりやすいので、多くのアプリケーションにおいて、こういったことは非常に早くなります。加えて、ボトルネックとなるものの多くは、JSの実行ではなく、DOMの変更です。Reactは変更の一括処理と検知を使うことによって、それを最適化しています。

- -

しかし、パフォーマンスについて、よりよい制御を持つことを求める時もあるでしょう。こういったケースで、Reactがサブツリーの処理をスキップすることを求めるなら、 shouldComponentUpdate() が単純にfalseを返すようにオーバーライドしてください。更に情報を得たい場合には、Reactのリファレンス文書を読んでください。

- -
-

注意: -shouldComponentUpdate() がデータが実際に変わった時にfalseを返したならば、ReactはUIを同期的に保つことができません。このメソッドを使う際には、何を行っているか理解してください。そして、顕著なパフォーマンスの問題がある時にだけ、この関数を使ってください。DOMと比較して、JavaScriptが速いことを過小評価しないでください。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/multiple-components-ko-KR.html b/docs/multiple-components-ko-KR.html deleted file mode 100644 index f6175a1860..0000000000 --- a/docs/multiple-components-ko-KR.html +++ /dev/null @@ -1,636 +0,0 @@ - - - - - - - 복합 컴포넌트 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 복합 컴포넌트 -

-
- -

지금까지, 단일 컴포넌트에서 데이터를 표시하고 유저 입력을 다루는 것을 살펴보았습니다. 다음엔 React의 최고의 기능 중 하나인 조합가능성(composability)을 살펴봅시다.

-

동기: 관심의 분리 #

-

명확히 정의된 인터페이스와 다른 컴포넌트를 재사용해 모듈러 컴포넌트를 구축하면, 함수와 클래스를 이용했을 때 얻을 수 있는 이점 대부분을 얻을 수 있습니다. 특히 앱에서 다른 관심을 분리할 수 있습니다.아무리 간단히 새 컴포넌트를 만들었다고 해도 말이죠. 당신의 애플리케이션에서 쓸 커스텀 컴포넌트 라이브러리를 만들어서, 당신의 도메인에 최적화된 방법으로 UI를 표현할 수 있게 됩니다.

-

조합(Composition) 예제 #

-

간단히 페이스북 그래프 API를 사용해 프로필 사진과 유저이름을 보여주는 아바타 컴포넌트를 만든다고 합시다.

-
var Avatar = React.createClass({
-  render: function() {
-    return (
-      <div>
-        <ProfilePic username={this.props.username} />
-        <ProfileLink username={this.props.username} />
-      </div>
-    );
-  }
-});
-
-var ProfilePic = React.createClass({
-  render: function() {
-    return (
-      <img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
-    );
-  }
-});
-
-var ProfileLink = React.createClass({
-  render: function() {
-    return (
-      <a href={'https://www.facebook.com/' + this.props.username}>
-        {this.props.username}
-      </a>
-    );
-  }
-});
-
-ReactDOM.render(
-  <Avatar username="pwh" />,
-  document.getElementById('example')
-);
-

소유권(Ownership) #

-

위의 예제에서, Avatar 인스턴스는 ProfilePicProfileLink인스턴스를 가지고 있습니다. React에서 소유자는 다른 컴포넌트의 props를 설정하는 컴포넌트입니다. 더 정식으로 말하면, X 컴포넌트가 Y 컴포넌트의 render() 메소드 안에서 만들어졌다면, YX소유하고 있다고 합니다. 앞에서 설명한 바와 같이, 컴포넌트는 자신의 props를 변경할 수 없습니다. props는 언제나 소유자가 설정한 것과 일치합니다. 이와 같은 근본적인 불변성은 UI가 일관성 있도록 해줍니다.

- -

소유(owner-ownee)관계와 부모·자식 관계를 구별하는 것은 중요합니다. 부모·자식 관계가 DOM에서부터 쓰던 익숙하고 이미 알고있던 단순한 것인 한편, 소유관계는 React 고유의 것입니다. 위의 예제에서, Avatardiv, ProfilePic, ProfileLink인스턴스를 소유하고, divProfilePicProfileLink인스턴스의 (소유자가 아닌) 부모입니다.

-

자식 #

-

React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트나 JavaScript 표현식을 시작과 끝 태그 사이에 넣을 수 있습니다. 이렇게 말이죠.

-
<Parent><Child /></Parent>
-
-

Parentthis.props.children라는 특수 prop으로 자식들을 읽을 수 있습니다. this.props.children 는 불투명한 데이터 구조이며, React.Children 유틸리티를 사용해 자식들을 관리합니다.

-

자식 Reconciliation (비교조정) #

-

Reconciliation은 React가 DOM을 각각 새로운 렌더 패스에 업데이트하는 과정입니다. 일반적으로, 자식은 렌더하는 순서에 따라 비교조정됩니다. 예를 들어, 각각의 마크업을 생성하는 두 개의 렌더 패스가 있다고 해봅시다.

-
// Render Pass 1
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// Render Pass 2
-<Card>
-  <p>Paragraph 2</p>
-</Card>
-
-

직관적으로 보면, <p>Paragraph 1</p>가 없어졌습니다만 그러는 대신에, React는 첫 번째 자식의 텍스트를 비교조정하고 마지막 자식을 파괴하도록 DOM을 비교조정할 것입니다. React는 자식들의 순서에 따라 비교조정합니다.

-

상태기반(Stateful) 자식 #

-

대부분의 컴포넌트에서는, 이것은 큰 문제가 아닙니다. 하지만 렌더 패스 간에 this.state를 유지하는 상태기반의 컴포넌트에서는 매우 문제가 될 수 있습니다.

- -

대부분의 경우, 이 문제는 엘리먼트를 파괴하지 않고 숨김으로써 피해갈 수 있습니다.

-
// Render Pass 1
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// Render Pass 2
-<Card>
-  <p style={{display: 'none'}}>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-

동적 자식 #

-

자식들이 섞이거나(검색의 결과같은 경우) 새로운 컴포넌트가 목록의 앞에 추가(스트림같은 경우)된다면 상황은 점점 더 까다로워집니다. 이런 때에의 동일성과 각 자식의 상태는 반드시 렌더 패스 간에 유지돼야 합니다. 각 자식에 key를 할당 함으로써 독자적으로 식별할 수 있습니다.

-
  render: function() {
-    var results = this.props.results;
-    return (
-      <ol>
-        {results.map(function(result) {
-          return <li key={result.id}>{result.text}</li>;
-        })}
-      </ol>
-    );
-  }
-
-

React가 키가 있는 자식들을 비교조정할 때, React는 key가 있는 자식이 (오염(clobbered)되는 대신) 재배치되고 (재사용되는 대신) 파괴되도록 보장할 것입니다.

- -

key항상 배열 안의 각 컴포넌트의 컨테이너 HTML 자식이 아닌 컴포넌트에게 직접 주어져야 합니다.

-
// 틀림!
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li key={this.props.data.id}>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-          return <ListItemWrapper data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
// 맞음 :)
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-           return <ListItemWrapper key={result.id} data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
-

ReactFragment 객체를 넘기는 것으로 자식에 키를 할당할 수도 있습니다. 자세한 내용은 키가 할당된 프래그먼트를 참고하세요.

-

데이터 흐름 #

-

React에서 데이터는 위에서 말한 것처럼 props를 통해 소유자로부터 소유한 컴포넌트로 흐릅니다. 이것은 사실상 단방향 데이터 바인딩입니다. 소유자는 propsstate를 기준으로 계산한 어떤 값으로 소유한 컴포넌트의 props를 바인드합니다. 이 과정은 재귀적으로 발생하므로, 데이터의 변경은 자동으로 모든 곳에 반영됩니다.

-

성능의 주의점 #

-

소유자가 가지고 있는 노드의 수가 많아지면 데이터가 변화하는 비용이 증가할 것으로 생각할 수도 있습니다. 좋은 소식은 JavaScript의 속도는 빠르고 render() 메소드는 꽤 간단한 경향이 있어, 대부분 애플리케이션에서 매우 빠르다는 점입니다. 덧붙여, 대부분의 병목 현상은 JS 실행이 아닌 DOM 변경에서 일어나고, React는 배치와 탐지 변경을 이용해 최적화해 줍니다.

- -

하지만, 가끔 성능을 위해 정교하게 제어해야 할 때도 있습니다. 이런 경우, React가 서브트리의 처리를 건너 뛰도록 간단히 shouldComponentUpdate()를 오버라이드해 false를 리턴하게 할 수 있습니다. 좀 더 자세한 정보는 React 참조 문서를 보세요.

- -
-

주의:

- -

데이터가 실제로는 변경되었지만 shouldComponentUpdate()가 false를 리턴한다면 React는 UI를 싱크시킬수 없습니다. 이 기능을 사용할 때에는 자신이 지금 무엇을 하고 있는지 알고 있고, 눈에 띄는 성능 문제가 있을 경우에만 사용하세요. JavaScript는 DOM에 비해 빠릅니다. 과소평가하지 마세요.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/multiple-components-zh-CN.html b/docs/multiple-components-zh-CN.html deleted file mode 100644 index 53c3304224..0000000000 --- a/docs/multiple-components-zh-CN.html +++ /dev/null @@ -1,636 +0,0 @@ - - - - - - - 复合组件 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 复合组件 -

-
- -

目前为止,我们已经学了如何用单个组件来展示数据和处理用户输入。下一步让我们来体验 React 最激动人心的特性之一:可组合性(composability)。

-

动机:关注分离 #

-

通过复用那些接口定义良好的组件来开发新的模块化组件,我们得到了与使用函数和类相似的好处。具体来说就是能够通过开发简单的组件把程序的不同关注面分离。如果为程序开发一套自定义的组件库,那么就能以最适合业务场景的方式来展示你的用户界面。

-

组合实例 #

-

让我们用 Facebook Graph API 来开发一个显示 Facebook 页面图片和用户名的简单 Avatar 组件吧。

-
var Avatar = React.createClass({
-  render: function() {
-    return (
-      <div>
-        <PagePic pagename={this.props.pagename} />
-        <PageLink pagename={this.props.pagename} />
-      </div>
-    );
-  }
-});
-
-var PagePic = React.createClass({
-  render: function() {
-    return (
-      <img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
-    );
-  }
-});
-
-var PageLink = React.createClass({
-  render: function() {
-    return (
-      <a href={'https://www.facebook.com/' + this.props.pagename}>
-        {this.props.pagename}
-      </a>
-    );
-  }
-});
-
-ReactDOM.render(
-  <Avatar pagename="Engineering" />,
-  document.getElementById('example')
-);
-

从属关系 #

-

上面例子中,Avatar 拥有 PagePicPageLink 的实例。拥有者 就是给其它组件设置 props 的那个组件。更正式地说,如果组件 Yrender() 方法是创建了组件 X,那么 Y 就拥有 X。上面讲过,组件不能修改自身的 props - 它们总是与它们的拥有者所设置的值保持一致。这是保持用户界面一致性的基本不变量。

- -

把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,而父子关系简单来讲就是 DOM 里的标签的关系。在上一个例子中,Avatar 拥有 divPagePicPageLink 实例,divPagePicPageLink 实例的父级(但不是拥有者)。

-

子级 #

-

实例化 React 组件时,你可以在开始标签和结束标签之间引用在React 组件或者Javascript 表达式:

-
<Parent><Child /></Parent>
-
-

Parent 能通过专门的 this.props.children prop 读取子级。this.props.children 是一个不透明的数据结构: 通过 React.Children 工具类 来操作。

-

子级校正(Reconciliation) #

-

校正就是每次 render 方法调用后 React 更新 DOM 的过程。 一般情况下,子级会根据它们被渲染的顺序来做校正。例如,下面代码描述了两次渲染的过程:

-
// 第一次渲染
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// 第二次渲染
-<Card>
-  <p>Paragraph 2</p>
-</Card>
-
-

直观来看,只是删除了<p>Paragraph 1</p>。事实上,React 先更新第一个子级的内容,然后删除最后一个组件。React 是根据子级的顺序来校正的。

-

子组件状态管理 #

-

对于大多数组件,这没什么大碍。但是,对于使用 this.state 来在多次渲染过程中里维持数据的状态化组件,这样做潜在很多问题。

- -

多数情况下,可以通过隐藏组件而不是删除它们来绕过这些问题。

-
// 第一次渲染
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// 第二次渲染
-<Card>
-  <p style={{display: 'none'}}>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-

动态子级 #

-

如果子组件位置会改变(如在搜索结果中)或者有新组件添加到列表开头(如在流中)情况会变得更加复杂。如果子级要在多个渲染阶段保持自己的特征和状态,在这种情况下,你可以通过给子级设置惟一标识的 key 来区分。

-
  render: function() {
-    var results = this.props.results;
-    return (
-      <ol>
-        {results.map(function(result) {
-          return <li key={result.id}>{result.text}</li>;
-        })}
-      </ol>
-    );
-  }
-
-

当 React 校正带有 key 的子级时,它会确保它们被重新排序(而不是破坏)或者删除(而不是重用)。

- -

务必把 key 添加到子级数组中的组件本身上,而不是数组中每个子级组件内部的最外层 HTML 上:

-
// 错误!
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li key={this.props.data.id}>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-          return <ListItemWrapper data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
// 正确 :)
-var ListItemWrapper = React.createClass({
-  render: function() {
-    return <li>{this.props.data.text}</li>;
-  }
-});
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <ul>
-        {this.props.results.map(function(result) {
-           return <ListItemWrapper key={result.id} data={result}/>;
-        })}
-      </ul>
-    );
-  }
-});
-
-

也可以传递 ReactFragment 对象来做有 key 的子级。详见Keyed Fragments

-

数据流 #

-

React 里,数据通过上面介绍过的 props 从拥有者流向归属者。这就是高效的单向数据绑定(one-way data binding):拥有者们通过它们的 propsstate 计算出一些值,并把这些值绑定到它们拥有的组件的 props 上。因为这个过程会递归地调用,所以数据变化会自动在所有它们被使用的地方反映出来。

-

性能提醒 #

-

你或许会担心如果一个拥有者有大量子级时,对于数据变化做出响应非常耗费性能。值得庆幸的是执行 JavaScript 非常的快,而且 render() 方法一般比较简单,所以在大部分应用里这样做速度极快。此外,性能的瓶颈大多是因为 DOM 更新,而非 JS 执行,而且 React 会通过批量更新和变化检测来优化性能。

- -

但是,有时候需要做细粒度的性能控制。这种情况下,可以重写 shouldComponentUpdate() 方法返回 false 来让 React 跳过对子树的处理。参考 React reference docs 了解更多。

- -
-

注意:

- -

如果在数据变化时让 shouldComponentUpdate() 返回 false,React 就不能保证用户界面同步。当使用它的时候一定确保你清楚到底做了什么,并且只在遇到明显性能问题的时候才使用它。不要低估 JavaScript 的速度,DOM 操作通常才是慢的原因。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/multiple-components.html b/docs/multiple-components.html index d97bc0b70c..e050a722f3 100644 --- a/docs/multiple-components.html +++ b/docs/multiple-components.html @@ -1,635 +1,10 @@ - - - - - - Multiple Components | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Multiple Components -

-
- -

So far, we've looked at how to write a single component to display data and handle user input. Next let's examine one of React's finest features: composability.

-

Motivation: Separation of Concerns #

-

By building modular components that reuse other components with well-defined interfaces, you get much of the same benefits that you get by using functions or classes. Specifically you can separate the different concerns of your app however you please simply by building new components. By building a custom component library for your application, you are expressing your UI in a way that best fits your domain.

-

Composition Example #

-

Let's create a simple Avatar component which shows a Facebook page picture and name using the Facebook Graph API.

-
class Avatar extends React.Component {
-  render() {
-    return (
-      <div>
-        <PagePic pagename={this.props.pagename} />
-        <PageLink pagename={this.props.pagename} />
-      </div>
-    );
-  }
-}
-
-class PagePic extends React.Component {
-  render() {
-    return (
-      <img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
-    );
-  }
-}
-
-class PageLink extends React.Component {
-  render() {
-    return (
-      <a href={'https://www.facebook.com/' + this.props.pagename}>
-        {this.props.pagename}
-      </a>
-    );
-  }
-}
-
-ReactDOM.render(
-  <Avatar pagename="Engineering" />,
-  document.getElementById('example')
-);
-

Ownership #

-

In the above example, instances of Avatar own instances of PagePic and PageLink. In React, an owner is the component that sets the props of other components. More formally, if a component X is created in component Y's render() method, it is said that X is owned by Y. As discussed earlier, a component cannot mutate its props — they are always consistent with what its owner sets them to. This fundamental invariant leads to UIs that are guaranteed to be consistent.

- -

It's important to draw a distinction between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, Avatar owns the div, PagePic and PageLink instances, and div is the parent (but not owner) of the PagePic and PageLink instances.

-

Children #

-

When you create a React component instance, you can include additional React components or JavaScript expressions between the opening and closing tags like this:

-
<Parent><Child /></Parent>
-
-

Parent can read its children by accessing the special this.props.children prop. this.props.children is an opaque data structure: use the React.Children utilities to manipulate them.

-

Child Reconciliation #

-

Reconciliation is the process by which React updates the DOM with each new render pass. In general, children are reconciled according to the order in which they are rendered. For example, suppose two render passes generate the following respective markup:

-
// Render Pass 1
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// Render Pass 2
-<Card>
-  <p>Paragraph 2</p>
-</Card>
-
-

Intuitively, <p>Paragraph 1</p> was removed. Instead, React will reconcile the DOM by changing the text content of the first child and destroying the last child. React reconciles according to the order of the children.

-

Stateful Children #

-

For most components, this is not a big deal. However, for stateful components that maintain data in this.state across render passes, this can be very problematic.

- -

In most cases, this can be sidestepped by hiding elements instead of destroying them:

-
// Render Pass 1
-<Card>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-// Render Pass 2
-<Card>
-  <p style={{display: 'none'}}>Paragraph 1</p>
-  <p>Paragraph 2</p>
-</Card>
-

Dynamic Children #

-

The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a key:

-
  render() {
-    return (
-      <ol>
-        {this.props.results.map((result) => (
-          <li key={result.id}>{result.text}</li>
-        ))}
-      </ol>
-    );
-  }
-
-

When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).

- -

The key should always be supplied directly to the components in the array, not to the container HTML child of each component in the array:

-
// WRONG!
-class ListItemWrapper extends React.Component {
-  render() {
-    return <li key={this.props.data.id}>{this.props.data.text}</li>;
-  }
-}
-class MyComponent extends React.Component {
-  render() {
-    return (
-      <ul>
-        {this.props.results.map((result) => (
-          <ListItemWrapper data={result} />
-        ))}
-      </ul>
-    );
-  }
-}
-
// Correct :)
-class ListItemWrapper extends React.Component {
-  render() {
-    return <li>{this.props.data.text}</li>;
-  }
-}
-class MyComponent extends React.Component {
-  render() {
-    return (
-      <ul>
-        {this.props.results.map((result) => (
-          <ListItemWrapper key={result.id} data={result} />
-        ))}
-      </ul>
-    );
-  }
-}
-
-

You can also key children by passing a ReactFragment object. See Keyed Fragments for more details.

-

Data Flow #

-

In React, data flows from owner to owned component through props as discussed above. This is effectively one-way data binding: owners bind their owned component's props to some value the owner has computed based on its props or state. Since this process happens recursively, data changes are automatically reflected everywhere they are used.

-

A Note on Performance #

-

You may be thinking that it's expensive to change data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and render() methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution. React will optimize this for you by using batching and change detection.

- -

However, sometimes you really want to have fine-grained control over your performance. In that case, simply override shouldComponentUpdate() to return false when you want React to skip processing of a subtree. See the React reference docs for more information.

- -
-

Note:

- -

If shouldComponentUpdate() returns false when data has actually changed, React can't keep your UI in sync. Be sure you know what you're doing while using it, and only use this function when you have a noticeable performance problem. Don't underestimate how fast JavaScript is relative to the DOM.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/optimizing-performance.html b/docs/optimizing-performance.html new file mode 100644 index 0000000000..984cc44301 --- /dev/null +++ b/docs/optimizing-performance.html @@ -0,0 +1,578 @@ + + + + + + + + + Optimizing Performance - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Optimizing Performance +

+
+ +

Internally, React uses several clever techniques to minimize the number of costly DOM operations required to update the UI. For many applications, using React will lead to a fast user interface without doing much work to specifically optimize for performance. Nevertheless, there are several ways you can speed up your React application.

+

Use The Production Build #

+

If you're benchmarking or experiencing performance problems in your React apps, make sure you're testing with the minified production build:

+ +
    +
  • For Create React App, you need to run npm run build and follow the instructions.
  • +
  • For single-file builds, we offer production-ready .min.js versions.
  • +
  • For Browserify, you need to run it with NODE_ENV=production.
  • +
  • For Webpack, you need to add this to plugins in your production config:
  • +
+
new webpack.DefinePlugin({
+  'process.env': {
+    NODE_ENV: JSON.stringify('production')
+  }
+}),
+new webpack.optimize.UglifyJsPlugin()
+
+

The development build includes extra warnings that are helpful when building your apps, but it is slower due to the extra bookkeeping it does.

+

Avoid Reconciliation #

+

React builds and maintains an internal representation of the rendered UI. It includes the React elements you return from your components. This representation lets React avoid creating DOM nodes and accessing existing ones beyond necessity, as that can be slower than operations on JavaScript objects. Sometimes it is referred to as a "virtual DOM", but it works the same way on React Native.

+ +

When a component's props or state change, React decides whether an actual DOM update is necessary by comparing the newly returned element with the previously rendered one. When they are not equal, React will update the DOM.

+ +

In some cases, your component can speed all of this up by overriding the lifecycle function shouldComponentUpdate, which is triggered before the re-rendering process starts. The default implementation of this function returns true, leaving React to perform the update:

+
shouldComponentUpdate(nextProps, nextState) {
+  return true;
+}
+
+

If you know that in some situations your component doesn't need to update, you can return false from shouldComponentUpdate instead, to skip the whole rendering process, including calling render() on this component and below.

+

shouldComponentUpdate In Action #

+

Here's a subtree of components. For each one, SCU indicates what shouldComponentUpdate returned, and vDOMEq indicates whether the rendered React elements were equivalent. Finally, the circle's color indicates whether the component had to be reconciled or not.

+ +
+ +

Since shouldComponentUpdate returned false for the subtree rooted at C2, React did not attempt to render C2, and thus didn't even have to invoke shouldComponentUpdate on C4 and C5.

+ +

For C1 and C3, shouldComponentUpdate returned true, so React had to go down to the leaves and check them. For C6 shouldComponentUpdate returned true, and since the rendered elements weren't equivalent React had to update the DOM.

+ +

The last interesting case is C8. React had to render this component, but since the React elements it returned were equal to the previously rendered ones, it didn't have to update the DOM.

+ +

Note that React only had to do DOM mutations for C6, which was inevitable. For C8, it bailed out by comparing the rendered React elements, and for C2's subtree and C7, it didn't even have to compare the elements as we bailed out on shouldComponentUpdate, and render was not called.

+

Examples #

+

If the only way your component ever changes is when the props.color or the state.count variable changes, you could have shouldComponentUpdate check that:

+
class CounterButton extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {count: 1};
+  }
+
+  shouldComponentUpdate(nextProps, nextState) {
+    if (this.props.color !== nextProps.color) {
+      return true;
+    }
+    if (this.state.count !== nextState.count) {
+      return true;
+    }
+    return false;
+  }
+
+  render() {
+    <button
+      color={this.props.color}
+      onClick={() => this.setState(state => ({count: state.count + 1}))}>
+      Count: {this.state.count}
+    </button>
+  }
+}
+
+

In this code, shouldComponentUpdate is just checking if there is any change in props.color or state.count. If those values don't change, the component doesn't update. If your component got more complex, you could use a similar pattern of doing a "shallow comparison" between all the fields of props and state to determine if the component should update. This pattern is common enough that React provides a helper to use this logic - just inherit from React.PureComponent. So this code is a simpler way to achieve the same thing:

+
class CounterButton extends React.PureComponent {
+  constructor(props) {
+    super(props);
+    this.state = {count: 1};
+  }
+
+  render() {
+    <button
+      color={this.props.color}
+      onClick={() => this.setState(state => ({count: state.count + 1}))}>
+      Count: {this.state.count}
+    </button>
+  }
+}
+
+

Most of the time, you can use React.PureComponent instead of writing your own shouldComponentUpdate. It only does a shallow comparison, so you can't use it if the props or state may have been mutated in a way that a shallow comparison would miss.

+ +

This can be a problem with more complex data structures. For example, let's say you want a ListOfWords component to render a comma-separated list of words, with a parent WordAdder component that lets you click a button to add a word to the list. This code does not work correctly:

+
class ListOfWords extends React.PureComponent {
+  render() {
+    return <div>{this.props.words.join(',')}</div>;
+  }
+}
+
+class WordAdder extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      words: ['marklar']
+    };
+    this.handleClick = this.handleClick.bind(this);
+  }
+
+  handleClick() {
+    // This section is bad style and causes a bug
+    const words = this.state.words;
+    words.push('marklar');
+    this.setState({words: words});
+  }
+
+  render() {
+    return (
+      <div>
+        <button onClick={this.handleClick} />
+        <ListOfWords words={this.state.words} />
+      </div>
+    );
+  }
+}
+
+

The problem is that PureComponent will do a simple comparison between the old and new values of this.props.words. Since this code mutates the words array in the handleClick method of WordAdder, the old and new values of this.props.words will compare as equal, even though the actual words in the array have changed. The ListOfWords will thus not update even though it has new words that shoud be rendered.

+

The Power Of Not Mutating Data #

+

The simplest way to avoid this problem is to avoid mutating values that you are using as props or state. For example, the handleClick method above could be rewritten using concat as:

+
handleClick() {
+  this.setState(prevState => ({
+    words: prevState.words.concat(['marklar'])
+  }));
+}
+
+

ES6 supports a spread syntax for arrays which can make this easier. If you're using Create React App, this syntax is available by default.

+
handleClick() {
+  this.setState(prevState => ({
+    words: [...prevState.words, 'marklar'],
+  }));
+};
+
+

You can also rewrite code that mutates objects to avoid mutation, in a similar way. For example, let's say we have an object named colormap and we want to write a function that changes colormap.right to be 'blue'. We could write:

+
function updateColorMap(colormap) {
+  colormap.right = 'blue';
+}
+
+

To write this without mutating the original object, we can use Object.assign method:

+
function updateColorMap(colormap) {
+  return Object.assign({}, colormap, {right: 'blue'});
+}
+
+

updateColorMap now returns a new object, rather than mutating the old one. Object.assign is in ES6 and requires a polyfill.

+ +

There is a JavaScript proposal to add object spread properties to make it easier to update objects without mutation as well:

+
function updateColorMap(colormap) {
+  return {...colormap, right: 'blue'};
+}
+
+

If you're using Create React App, both Object.assign and the object spread syntax are available by default.

+

Using Immutable Data Structures #

+

Immutable.js is another way to solve this problem. It provides immutable, persistent collections that work via structural sharing:

+ +
    +
  • Immutable: once created, a collection cannot be altered at another point in time.
  • +
  • Persistent: new collections can be created from a previous collection and a mutation such as set. The original collection is still valid after the new collection is created.
  • +
  • Structural Sharing: new collections are created using as much of the same structure as the original collection as possible, reducing copying to a minimum to improve performance.
  • +
+ +

Immutability makes tracking changes cheap. A change will always result in a new object so we only need to check if the reference to the object has changed. For example, in this regular JavaScript code:

+
var x = { foo: "bar" };
+var y = x;
+y.foo = "baz";
+x === y; // true
+
+

Although y was edited, since it's a reference to the same object as x, this comparison returns true. You can write similar code with immutable.js:

+
var SomeRecord = Immutable.Record({ foo: null });
+var x = new SomeRecord({ foo: 'bar'  });
+var y = x.set('foo', 'baz');
+x === y; // false
+
+

In this case, since a new reference is returned when mutating x, we can safely assume that x has changed.

+ +

Two other libraries that can help use immutable data are seamless-immutable and immutability-helper.

+ +

Immutable data structures provide you with a cheap way to track changes on objects, which is all we need to implement shouldComponentUpdate. This can often provide you with a nice performance boost.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/package-management.html b/docs/package-management.html deleted file mode 100644 index b138cf3ade..0000000000 --- a/docs/package-management.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - - Package Management | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Package Management -

-
- -

CDN-hosted React #

-

We provide CDN-hosted versions of React on our download page. These pre-built files use the UMD module format. Dropping them in with a simple <script> tag will inject the React and ReactDOM globals into your environment. It should also work out-of-the-box in CommonJS and AMD environments.

-

Using React from npm #

-

You can use React with a CommonJS module system like browserify or webpack. Use the react and react-dom npm packages.

-
// main.js
-var React = require('react');
-var ReactDOM = require('react-dom');
-
-ReactDOM.render(
-  <h1>Hello, world!</h1>,
-  document.getElementById('example')
-);
-
-

Configure babel with a .babelrc file:

-
 { "presets": ["react"] }
-
-
-

Note:

- -

If you are using ES2015, you will want to also use the babel-preset-es2015 package.

-
- -

To install React DOM and build your bundle with browserify:

-
$ npm install --save react react-dom babelify babel-preset-react
-$ browserify -t [ babelify ] main.js -o bundle.js
-
-

To install React DOM and build your bundle with webpack:

-
$ npm install --save react react-dom babel-preset-react babel-loader babel-core
-$ webpack main.js bundle.js --module-bind 'js=babel-loader'
-
-
-

Note:

- -

If you are using ES2015, you will want to also use the babel-preset-es2015 package.

-
- -

Note: by default, React will be in development mode, which is slower, and not advised for production. To use React in production mode, set the environment variable NODE_ENV to production (using envify or webpack's DefinePlugin). For example:

-
new webpack.DefinePlugin({
-  "process.env": {
-    NODE_ENV: JSON.stringify("production")
-  }
-});
-
-

Update your HTML file as below:

-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script src="bundle.js"></script>
-  </body>
-</html>
-

Using React from Bower #

-

Bower is a package manager optimized for the front-end development. If multiple packages depend on a package - jQuery for example - Bower will download jQuery just once. This is known as a flat dependency graph and it helps reduce page load. For more info, visit http://bower.io/.

- -

If you'd like to use bower, it's as easy as:

-
bower install --save react
-
<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello React!</title>
-    <script src="bower_components/react/react.js"></script>
-    <script src="bower_components/react/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  </head>
-  <body>
-    <div id="example"></div>
-    <script type="text/babel">
-      ReactDOM.render(
-        <h1>Hello, world!</h1>,
-        document.getElementById('example')
-      );
-    </script>
-  </body>
-</html>
-

Using master #

-

We have instructions for building from master in our GitHub repository.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/perf-it-IT.html b/docs/perf-it-IT.html deleted file mode 100644 index c0a7e8c575..0000000000 --- a/docs/perf-it-IT.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - Strumenti per la Performance | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Strumenti per la Performance -

-
- -

React è solitamente assai veloce. Tuttavia, in situazioni nelle quali devi spremere fino all'ultima goccia di prestazioni dalla tua applicazione, fornisce un hook shouldComponentUpdate nel quale puoi aggiungere controlli di ottimizzazione per l'algoritmo di confronto di React.

- -

Oltre a darti una panoramica sulle prestazioni generali della tua applicazione, ReactPerf è uno strumento di profilazione che ti dice esattamente dove è necessario aggiungere questi hook.

- -
-

Nota:

- -

La build di sviluppo di React è più lenta della build di produzione, per via di tutta la logica aggiuntiva per fornire, ad esempio, gli avvisi amichevoli di React nella console (eliminati dalla build di produzione). Pertanto, il profilatore serve soltanto ad indicare le parti relativamente costose della tua applicazione.

-
-

API Generale #

-

L'oggetto Perf documentato di seguito è esposto come React.addons.Perf quando si usa la build react-with-addons.js in modalità di sviluppo.

-

Perf.start() and Perf.stop() #

-

Avvia/interrompe la misurazione. Le operazioni React intermedie sono registrate per analisi in seguito. Le operazioni che hanno impiegato un tempo trascurabile vengono ignorate.

- -

Dopo l'interruzione, dovrai chiamare Perf.getLastMeasurements() (descritta in seguito) per ottenere le misurazioni.

-

Perf.printInclusive(measurements) #

-

Stampa il tempo complessivo impiegato. Se non vengono passati argomenti, stampa tutte le misurazioni dall'ultima registrazione. Stampa una tabella gradevolmente formattata nella console, come segue:

- -

-

Perf.printExclusive(measurements) #

-

I tempi "esclusivi" non includono il tempo impiegato a montare i componenti: processare le proprietà, getInitialState, chiamare componentWillMount e componentDidMount, etc.

- -

-

Perf.printWasted(measurements) #

-

La parte più utile in assoluto del profilatore.

- -

Il tempo "sprecato" è impiegato nei componenti che non hanno di fatto visualizzato nulla, ad es. il rendering è rimasto inalterato, quindi il DOM non è stato toccato.

- -

-

Perf.printDOM(measurements) #

-

Stampa le manipolazioni sottostanti del DOM, ad es. "imposta innerHTML" e "rimuovi".

- -

-

API Avanzata #

-

I metodi di stampa precedenti utilizzano Perf.getLastMeasurements() per effettuare una gradevole stampa dei risultati.

-

Perf.getLastMeasurements() #

-

Ottieni l'array delle misurazioni dall'ultima sessione di avvio-interruzione. L'array contiene oggetti, ciascuno dei quali assomiglia a quanto segue:

-
{
-  // I termini "inclusive" ed "exclusive" sono spiegati in seguito
-  "exclusive": {},
-  // '.0.0' è l'identificativo React del nodo
-  "inclusive": {".0.0": 0.0670000008540228, ".0": 0.3259999939473346},
-  "render": {".0": 0.036999990697950125, ".0.0": 0.010000003385357559},
-  // Numero di istanze
-  "counts": {".0": 1, ".0.0": 1},
-  // Scritture sul DOM
-  "writes": {},
-  // Informazioni aggiuntive per il debug
-  "displayNames": {
-    ".0": {"current": "App", "owner": "<root>"},
-    ".0.0": {"current": "Box", "owner": "App"}
-  },
-  "totalTime": 0.48499999684281647
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/perf-ja-JP.html b/docs/perf-ja-JP.html deleted file mode 100644 index 932d151d59..0000000000 --- a/docs/perf-ja-JP.html +++ /dev/null @@ -1,551 +0,0 @@ - - - - - - - パフォーマンスツール | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- パフォーマンスツール -

-
- -

Reactは普通、従来の枠を超えてとても速いです。しかし、アプリケーションにおいて、少しでもパフォーマンスを上げようという状況では、Reactの差分を取るアルゴリズムを最大限活用するヒントが得られる、shouldComponentUpdateのフックを提供します。

- -

アプリケーション全体のパフォーマンスについての要約を得ることに加えて、ReactPerfはそれらのフックを実際にはどこに配置する必要があるか教えてくれるプロファイリングツールでもあります。

- -
-

注意: -Reactの開発版のビルドは与えられた外部ロジックのためにプロダクション版のビルドよりも遅くなります。例えば、Reactのフレンドリーコンソールの警告(プロダクション版のビルドにおいては警告が出ません)のように。それゆえ、プロファイラは 比較的 コストがかかっている箇所のみを指し示します。

-
-

一般的なAPI #

-

ここに記述されている Perf オブジェクトは react-with-addons.js を開発版でビルドしたものを使用する際に React.addons.Perf として表されます。

-

Perf.start()Perf.stop() #

-

測定の開始/終了です。その間のReactの操作は以下のような分析のために記録されます。あまり時間を使わない操作は無視されます。

- -

停止した後、あなたは、測定結果を得るために Perf.getLastMeasurements() (後述)が必要になります。

-

Perf.printInclusive(measurements) #

-

かかった全ての時間を出力します。引数が渡されなかった場合は、デフォルトで最後の測定から全ての測定が行われます。これは以下のように、コンソールに綺麗にフォーマットされたテーブルを出力します。

- -

-

Perf.printExclusive(measurements) #

-

「占有」時間はコンポーネントをマウントするのにかかった時間を含みません。プロパティの処理、 getInitialState , componentWillMountcomponentDidMount の呼び出しなどは含みます。

- -

-

Perf.printWasted(measurements) #

-

プロファイラの最も有用な箇所です

- -

「無駄な」時間はコンポーネントが実際には何もレンダリングしていないのにかかっている時間です。例えば、同じものをレンダリングしたので、DOMが触られなかったような場合です。

- -

-

Perf.printDOM(measurements) #

-

以下のような、DOMの操作を出力します。例えば、"set innerHTML"や"remove"といったものです。

- -

-

先進的なAPI #

-

上記の出力メソッドは結果をプリティプリントするのに Perf.getLastMeasurements() を使用しています。

-

Perf.getLastMeasurements() #

-

最後の開始と終了のセッションから測定の配列を取得します。配列は以下のようなオブジェクトを含みます。

-
{
-  // "inclusive"と"exclusive"の期間は以下で説明されています
-  "exclusive": {},
-  // '.0.0' はノードのReact ID
-  "inclusive": {".0.0": 0.0670000008540228, ".0": 0.3259999939473346},
-  "render": {".0": 0.036999990697950125, ".0.0": 0.010000003385357559},
-  // インスタンスの数
-  "counts": {".0": 1, ".0.0": 1},
-  // 触ったDOM
-  "writes": {},
-  // 追加のデバッグ情報
-  "displayNames": {
-    ".0": {"current": "App", "owner": "<root>"},
-    ".0.0": {"current": "Box", "owner": "App"}
-  },
-  "totalTime": 0.48499999684281647
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/perf-ko-KR.html b/docs/perf-ko-KR.html deleted file mode 100644 index 357c292a3e..0000000000 --- a/docs/perf-ko-KR.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - 성능 도구 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 성능 도구 -

-
- -

React는 보통 처음에는 꽤 빠릅니다. 하지만 모든 성능을 짜내야 하는 상황일 때를 위해, React는 shouldComponentUpdate 훅을 제공해 React의 diff 알고리즘을 위한 최적화 힌트를 추가할 수 있습니다.

- -

덧붙여 앱의 전반적인 성능의 개요도 제공합니다. ReactPerf는 프로파일링 도구로 정확히 어디에 훅이 필요한지 알려줍니다.

- -
-

주의:

- -

React의 개발 빌드는 제공되는 추가 기능으로 인해 프로덕션 빌드보다 느립니다. 추가 기능에는 React의 친절한 콘솔 경고같은 것이 있습니다.(이는 프로덕션 빌드에서는 제거 됩니다) 따라서, 프로파일러는 앱의 상대적으로 비싼 부분만 표시하도록 합니다.

-
-

일반 API #

-

여기에서 설명하는 Perf 객체는 require('react-addons-perf')로 노출되고 React 개발 모드에서만 사용할 수 있습니다. 이 번들을 프로덕션에서 앱과 같이 빌드하시면 안됩니다.

-

Perf.start()Perf.stop() #

-

측정을 시작/정지합니다. 그 사이의 React 연산은 밑에 있는 분석을 하기위해 기록됩니다. 미미한 양의 연산은 무시됩니다.

- -

종료 후, 측정을 하기위해서는 이후에 설명할 Perf.getLastMeasurements()가 필요합니다.

-

Perf.printInclusive(measurements) #

-

전 수행 시간을 출력합니다. 인자가 넘겨지지 않으면, 기본값은 지난 기록부터의 모든 측정이 됩니다. 이 출력은 밑에 있는 것처럼 콘솔에서 깔끔한 테이블로 그려집니다.

- -

-

Perf.printExclusive(measurements) #

-

컴포넌트를 마운트하는 시간을 포함하지 않은 "exclusive" 시간입니다. 여기에는 props 연산, getInitialState, componentWillMount 호출, componentDidMount등이 포함됩니다.

- -

-

Perf.printWasted(measurements) #

-

프로파일러에서 가장 유용한 부분입니다.

- -

렌더가 같아서, DOM을 변경(touch)하지 않는 경우같은 실제로는 아무것도 렌더하지 않는 컴포넌트가 사용하는 "낭비되는" 시간을 출력합니다.

- -

-

Perf.printDOM(measurements) #

-

"set innerHTML"이나 "remove"같은 기저의 DOM 조작을 출력합니다.

- -

-

고급 API #

-

위의 출력 메소드에 Perf.getLastMeasurements()를 사용해 결과를 이쁘게 출력합니다.

-

Perf.getLastMeasurements() #

-

마지막 start-stop 세션에서 측정들의 배열을 가져옵니다. 이 배열은 이런 객체들을 가지고 있습니다.

-
{
-  // 용어 "inclusive"와 "exclusive"는 위에서 설명했음
-  "exclusive": {},
-  // '.0.0'는 노드의 React ID
-  "inclusive": {".0.0": 0.0670000008540228, ".0": 0.3259999939473346},
-  "render": {".0": 0.036999990697950125, ".0.0": 0.010000003385357559},
-  // 인스턴스의 수
-  "counts": {".0": 1, ".0.0": 1},
-  // DOM 변경(touch)
-  "writes": {},
-  // 추가 디버깅 정보
-  "displayNames": {
-    ".0": {"current": "App", "owner": "<root>"},
-    ".0.0": {"current": "Box", "owner": "App"}
-  },
-  "totalTime": 0.48499999684281647
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/perf-zh-CN.html b/docs/perf-zh-CN.html deleted file mode 100644 index 727dbfb1e0..0000000000 --- a/docs/perf-zh-CN.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - 性能工具 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 性能工具 -

-
- -

React 通常是相当快的。然而,在你需要压榨你的 app 的每一分性能的情况下,它提供了一个shouldComponentUpdate 钩子,在此你可以添加优化提示到 React 的 diff 算法里。

- -

除了给予你一个你的 app 的整体性能概览外,ReactPerf 还是一个准确告诉你,你需要在哪里放置这些钩子的分析工具。

-

General API #

-

这里陈述的 Perf 对象被用 require('react-addons-perf') 暴露,并且只能被使用在 React 的开发模式。你不应在生产环境下在你的 app 包含这个包。

- -
-

注意:

- -

开发版的 React 慢于生产版,因为所有额外提供的逻辑,例如,React 的友好的控制台警告 (在生产版中被除去)。因此,分析工具仅服务于指示你的 app 相对 昂贵的部分。

-
-

Perf.start() and Perf.stop() #

-

开始/停止测量。其间的React操作被记录用于之后的分析。产生无关紧要时间的操作被忽略。

- -

在停止以后,你将需要 Perf.getLastMeasurements() (下面将介绍)来获取测量结果。

-

Perf.printInclusive(measurements) #

-

打印总体花费的时间。如果没有传入参数,默认是从上次记录的所有测量数据。它在控制台里打印良好格式化的结果,像这样:

- -

-

Perf.printExclusive(measurements) #

-

"独占的"时间不包括花费于加载组件的时间: 处理 props, getInitialState, 调用 componentWillMountcomponentDidMount, 等等。

- -

-

Perf.printWasted(measurements) #

-

分析工具里最有用的部分.

- -

"垃圾"时间是花费在组件上实际没有绘制任何东西的时间,例如渲染结果总是相同,所以 DOM 没有被触碰到。

- -

-

Perf.printDOM(measurements) #

-

打印底层的 DOM 操纵,例如 "set innerHTML" 和 "remove".

- -

-

Advanced API #

-

以上的打印方法使用 Perf.getLastMeasurements() 来美观的打印结果。

-

Perf.getLastMeasurements() #

-

从最后的 start-stop 会话获取测量数据数据。这个数组包含对象,每个看起来像这样:

-
{
-  // The term "inclusive" and "exclusive" are explained below
-  "exclusive": {},
-  // '.0.0' is the React ID of the node
-  "inclusive": {".0.0": 0.0670000008540228, ".0": 0.3259999939473346},
-  "render": {".0": 0.036999990697950125, ".0.0": 0.010000003385357559},
-  // Number of instances
-  "counts": {".0": 1, ".0.0": 1},
-  // DOM touches
-  "writes": {},
-  // Extra debugging info
-  "displayNames": {
-    ".0": {"current": "App", "owner": "<root>"},
-    ".0.0": {"current": "Box", "owner": "App"}
-  },
-  "totalTime": 0.48499999684281647
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/perf.html b/docs/perf.html index 7bbc70a166..e7f7bca014 100644 --- a/docs/perf.html +++ b/docs/perf.html @@ -1,12 +1,14 @@ + + - Performance Tools | React - - + Performance Tools - React + + @@ -44,31 +46,142 @@
-
+
+ Edit on GitHub +

+ Performance Tools +

+
+ +

Importing

+
import Perf from 'react-addons-perf' // ES6
+var Perf = require('react-addons-perf') // ES5 with npm
+var Perf = React.addons.Perf; // ES5 with react-with-addons.js
+

Overview #

+

React is usually quite fast out of the box. However, in situations where you need to squeeze every ounce of performance out of your app, it provides a shouldComponentUpdate() hook where you can add optimization hints to React's diff algorithm.

+ +

In addition to giving you an overview of your app's overall performance, Perf is a profiling tool that tells you exactly where you need to put these hooks.

+ +

See these articles by the Benchling Engineering Team for a in-depth introduction to performance tooling:

+ + +

Development vs. Production Builds #

+

If you're benchmarking or seeing performance problems in your React apps, make sure you're testing with the minified production build. The development build includes extra warnings that are helpful when building your apps, but it is slower due to the extra bookkeeping it does.

+ +

However, the perf tools described on this page only work when using the development build of React. Therefore, the profiler only serves to indicate the relatively expensive parts of your app.

+

Using Perf #

+

The Perf object can be used with React in development mode only. You should not include this bundle when building your app for production.

+

Getting Measurements #

+ +

Printing Results #

+

The following methods use the measurements returned by Perf.getLastMeasurements() to pretty-print the result.

+ + + +
+

Reference #

start() #

stop() #

Perf.start()
+// ...
+Perf.stop()
+
+

Start/stop the measurement. The React operations in-between are recorded for analyses below. Operations that took an insignificant amount of time are ignored.

+ +

After stopping, you will need Perf.getLastMeasurements() to get the measurements.

+ +
+

getLastMeasurements() #

Perf.getLastMeasurements()
+
+

Get the opaque data structure describing measurements from the last start-stop session. You can save it and pass it to the other print methods in Perf to analyze past measurements.

+ +
+

Note

+ +

Don't rely on the exact format of the return value because it may change in minor releases. We will update the documentation if the return value format becomes a supported part of the public API.

+
+ +
+

printInclusive() #

Perf.printInclusive(measurements)
+
+

Prints the overall time taken. If no argument's passed, defaults to all the measurements from the last recording. This prints a nicely formatted table in the console, like so:

+ +

+ +
+

printExclusive() #

Perf.printExclusive(measurements)
+
+

"Exclusive" times don't include the times taken to mount the components: processing props, calling componentWillMount and componentDidMount, etc.

+ +

+ +
+

printWasted() #

Perf.printWasted(measurements)
+
+

The most useful part of the profiler.

+ +

"Wasted" time is spent on components that didn't actually render anything, e.g. the render stayed the same, so the DOM wasn't touched.

+ +

+ +
+

printOperations() #

Perf.printOperations(measurements)
+
+

Prints the underlying DOM manipulations, e.g. "set innerHTML" and "remove".

+ +

+ +
+

printDOM() #

Perf.printDOM(measurements)
+
+

This method has been renamed to printOperations(). Currently printDOM() still exists as an alias but it prints a deprecation warning and will eventually be removed.

+ + +
+ + ← Prev + + + Next → + +
+
+ - - - - + + + + - - - - - - - @@ -433,84 +416,57 @@
+ - -
- Edit on GitHub -

- Performance Tools -

-
- -

React is usually quite fast out of the box. However, in situations where you need to squeeze every ounce of performance out of your app, it provides a shouldComponentUpdate hook where you can add optimization hints to React's diff algorithm.

- -

In addition to giving you an overview of your app's overall performance, ReactPerf is a profiling tool that tells you exactly where you need to put these hooks.

- -

See these two articles by the Benchling Engineering Team for a in-depth introduction to performance tooling: "Performance Engineering with React" and "A Deep Dive into React Perf Debugging"!

-

Development vs. Production Builds #

-

If you're benchmarking or seeing performance problems in your React apps, make sure you're testing with the minified production build. The development build includes extra warnings that are helpful when building your apps, but it is slower due to the extra bookkeeping it does.

- -

However, the perf tools described on this page only work when using the development build of React. Therefore, the profiler only serves to indicate the relatively expensive parts of your app.

-

General API #

-

The Perf object documented here is exposed as require('react-addons-perf') and can be used with React in development mode only. You should not include this bundle when building your app for production.

-

Perf.start() and Perf.stop() #

-

Start/stop the measurement. The React operations in-between are recorded for analyses below. Operations that took an insignificant amount of time are ignored.

- -

After stopping, you will need Perf.getLastMeasurements() (described below) to get the measurements.

-

Perf.printInclusive(measurements) #

-

Prints the overall time taken. If no argument's passed, defaults to all the measurements from the last recording. This prints a nicely formatted table in the console, like so:

- -

-

Perf.printExclusive(measurements) #

-

"Exclusive" times don't include the times taken to mount the components: processing props, getInitialState, call componentWillMount and componentDidMount, etc.

- -

-

Perf.printWasted(measurements) #

-

The most useful part of the profiler.

- -

"Wasted" time is spent on components that didn't actually render anything, e.g. the render stayed the same, so the DOM wasn't touched.

- -

-

Perf.printOperations(measurements) #

-

Prints the underlying DOM manipulations, e.g. "set innerHTML" and "remove".

- -

-

Perf.printDOM(measurements) #

-

This method has been renamed to printOperations() which is described in the previous paragraph. Currently printDOM() still exists as an alias but it prints a deprecation warning and will eventually be removed.

-

Advanced API #

-

The above print methods use Perf.getLastMeasurements() to pretty-print the result.

-

Perf.getLastMeasurements() #

-

Get the opaque data structure describing measurements from the last start-stop session. You can save it and pass it to the methods above to analyze past measurements.

- -

Don't rely on the exact format of the return value because it may change in minor releases. We will update the documentation if the return value format becomes a supported part of the public API.

- - -
- - ← Prev - - - Next → - -
-
- - -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- PureRenderMixin -

-
- -

Se la funzione render del tuo componente React è "pura" (in altre parole, visualizza lo stesso risultato a partire dagli stessi proprietà e stato), puoi usare questo mixin per un incremento di prestazioni in alcuni casi.

- -

Esempio:

-
var PureRenderMixin = require('react/addons').addons.PureRenderMixin;
-React.createClass({
-  mixins: [PureRenderMixin],
-
-  render: function() {
-    return <div className={this.props.className}>foo</div>;
-  }
-});
-
-

Dietro le quinte, il mixin implementa shouldComponentUpdate, nel quale confronta i valori attuali di this.props e this.state con i successivi e restituisce false se l'uguaglianza è verificata.

- -
-

Nota:

- -

Questo confronto tra gli oggetti è soltanto superficiale. Se questi contengono strutture dati complesse, può causare dei falsi negativi per differenze in profondità. Effettua il mix in componenti la cui struttura di this.props e this.state sia semplice, oppure utilizza forceUpdate() quando si ha la certezza che le strutture dati siano cambiate in profondità. In alternativa, considera l'utilizzo di oggetti immutabili per facilitare il confronto rapido di oggetti annidati.

- -

Inoltre, shouldComponentUpdate rimanda gli aggiornamenti per l'intero sotto albero di componenti. Assicurati che tutti i componenti figli siano anch'essi "puri".

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/pure-render-mixin-ja-JP.html b/docs/pure-render-mixin-ja-JP.html deleted file mode 100644 index 2cffc78cdc..0000000000 --- a/docs/pure-render-mixin-ja-JP.html +++ /dev/null @@ -1,517 +0,0 @@ - - - - - - - PureRenderMixin | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- PureRenderMixin -

-
- -

Reactコンポーネントのrender関数が「ピュア」である(言い換えると、同じpropsやstateが与えられた時に同じ結果をレンダリングする)場合は、いくつかのケースでパフォーマンスをあげるためにこのミックスインを使用することができます。

- -

例:

-
var PureRenderMixin = require('react/addons').addons.PureRenderMixin;
-React.createClass({
-  mixins: [PureRenderMixin],
-
-  render: function() {
-    return <div className={this.props.className}>foo</div>;
-  }
-});
-
-

内部で、このミックスインはshouldComponentUpdateを実行します。現在のpropsとstateを次のものと比較し、同様のものであれば、 false を返します。

- -
-

注意: -このミックスインはオブジェクトの比較のみを行います。それらが複雑なデータ構造を持っていた場合、深い位置における違いは見逃されることがあります。単純なpropsやstateをコンポーネントが持っている場合にのみ、使用してください。深いデータ構造が変更されることが分かっている場合は、 forceUpdate() を使用してください。または、ネストされたデータの比較を速く行うために不変オブジェクトの使用を考えてみてください。 -更に、 shouldComponentUpdate は全てのコンポーネントのサブツリーのアップデートをスキップします。全ての子要素のコンポーネントもまた、「ピュア」であることを確認してください。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/pure-render-mixin-ko-KR.html b/docs/pure-render-mixin-ko-KR.html deleted file mode 100644 index b17330a664..0000000000 --- a/docs/pure-render-mixin-ko-KR.html +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - - PureRenderMixin | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- PureRenderMixin -

-
- -

React 컴포넌트의 렌더 함수가 "pure"하다면 (다른 말로, props나 state에 같은 값이 주어질 때 같은 결과를 렌더한다면) 몇몇 경우엔 이 믹스인을 사용하여 성능을 향상시킬 수 있습니다.

- -

예제:

-
var PureRenderMixin = require('react-addons-pure-render-mixin');
-React.createClass({
-  mixins: [PureRenderMixin],
-
-  render: function() {
-    return <div className={this.props.className}>foo</div>;
-  }
-});
-
-

내부적으로 믹스인은 현재의 props와 state를 다음 값과 비교하여 같다면 false를 반환하도록 shouldComponentUpdate를 구현합니다.

- -
-

주의:

- -

여기서는 객체에 대한 얕은(shallow) 비교만 합니다. 복잡한 데이터 구조를 가진 경우에는 깊은 부분의 차이에 대해 잘못된 false를 반환 할 수도 있습니다. 간단한 props와 state를 사용하는 컴포넌트에만 적용하거나 깊은 데이터 구조가 변경 되었을때는 forceUpdate()를 사용하세요. 아니면 중첩 데이터의 비교를 빠르고 용이하게 하기 위해 immutable 객체의 도입을 고려해보세요.

- -

또, shouldComponentUpdate는 컴포넌트 서브트리의 업데이트를 건너뜁니다. 모든 자식 컴포넌트들도 "pure"한지 확인하세요.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/pure-render-mixin-zh-CN.html b/docs/pure-render-mixin-zh-CN.html deleted file mode 100644 index ca6e58714d..0000000000 --- a/docs/pure-render-mixin-zh-CN.html +++ /dev/null @@ -1,532 +0,0 @@ - - - - - - - PureRenderMixin | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- PureRenderMixin -

-
- -

如果你的 React 组件的 render 函数是 "纯净" 的(换句话说,它的渲染在给定相同的 props 和 state 时返回相同的结果),你可以使用这个 mixin 在某些情况下进行性能加速。

- -

例子:

-
var PureRenderMixin = require('react-addons-pure-render-mixin');
-React.createClass({
-  mixins: [PureRenderMixin],
-
-  render: function() {
-    return <div className={this.props.className}>foo</div>;
-  }
-});
-
-

使用 ES6 class 语法的例子:

-
import PureRenderMixin from 'react-addons-pure-render-mixin';
-class FooComponent extends React.Component {
-  constructor(props) {
-    super(props);
-    this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
-  }
-
-  render() {
-    return <div className={this.props.className}>foo</div>;
-  }
-}
-
-

在内部, mixin 实现了 shouldComponentUpdate, 它对当前及下一步的 props 和 state 进行比较,并当相等时返回 false

- -
-

注意:

- -

它仅仅浅比较对象。如果包含了复杂的对象,可能会对于深层的不同产生 false-negatives。只 mix 到那些含有简单 props 和 state 的组件,或者在你知道深层对象改变时使用 forceUpdate() 。或者,考虑使用immutable objects 来促进快速的嵌套数据比较。

- -

此外, shouldComponentUpdate 跳过了整个子树的更新。确保所有的子组件都是 "纯净" 的。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/pure-render-mixin.html b/docs/pure-render-mixin.html index d126a78de3..7f9908c00b 100644 --- a/docs/pure-render-mixin.html +++ b/docs/pure-render-mixin.html @@ -1,12 +1,14 @@ + + - PureRenderMixin | React - - + PureRenderMixin - React + + @@ -44,406 +46,45 @@
- - - -
- -
+ +
+ +
+ + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ React Top-Level API +

+
+ +

React is the entry point to the React library. If you use React as a script tag, these top-level APIs are available on the React global. If you use ES6 with npm, you can write import React from 'react'. If you use ES5 with npm, you can write var React = require('react').

+

Overview #

Components #

+

React components let you split the UI into independent, reusable pieces, and think about each piece in isolation. React components can be defined by subclassing React.Component or React.PureComponent.

+ + + +

If you don't use ES6 classes, you may use this helper instead.

+ + +

Creating React Elements #

+

We recommend using JSX to describe what your UI should look like. Each JSX element is just syntactic sugar for calling React.createElement(). You will not typically invoke the following methods directly if you are using JSX.

+ + + +

See Using React without JSX for more information.

+

Transforming Elements #

+

React also provides some other APIs:

+ + +

Typechecking with PropTypes #

+

You can use React.PropTypes to run typechecking on the props for a component.

+ + + +

Validators treat props as optional by default. You can use isRequired to make sure a warning is shown if the prop is not provided.

+ + +

Add-Ons #

+

If you're using react-with-addons.js, the React Add-Ons will be available via React.addons.

+ + + +
+

Reference #

React.Component #

+

React.Component is the base class for React components when they are defined using ES6 classes.

+
class Greeting extends React.Component {
+  render() {
+    return <h1>Hello, {this.props.name}</h1>;
+  }
+}
+
+

See the React.Component API Reference for a list of methods and properties related to the base React.Component class.

+ +
+

React.PureComponent #

+

React.PureComponent is exactly like React.Component but implements shouldComponentUpdate() with a shallow prop and state comparison.

+ +

If your React component's render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.

+ +
+

Note

+ +

React.PureComponent's shouldComponentUpdate() only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only mix into components which have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data.

+ +

Furthermore, React.PureComponent's shouldComponentUpdate() skips prop updates for the whole component subtree. Make sure all the children components are also "pure".

+
+ +
+

createClass() #

React.createClass(specification)
+
+

If you don't use ES6 yet, you may use the React.createClass() helper instead to create a component class.

+
var Greeting = React.createClass({
+  render: function() {
+    return <h1>Hello, {this.props.name}</h1>;
+  }
+});
+
+

See Using React without ES6 for more information.

+ +
+

createElement() #

React.createElement(
+  type,
+  [props],
+  [...children]
+)
+
+

Create and return a new React element of the given type. The type argument can be either an +html tag name string (eg. 'div', 'span', etc), or a React class (created via React.createClass()).

+ +

Code written with JSX will be converted to use React.createElement(). You will not typically invoke React.createElement() directly if you are using JSX. See React Without JSX to learn more.

+ +

Convenience wrappers around React.createElement() for DOM components are provided by React.DOM. For example, React.DOM.a(...) is a convenience wrapper for React.createElement('a', ...).

+ +
+

cloneElement() #

React.cloneElement(
+  element,
+  [props],
+  [...children]
+)
+
+

Clone and return a new React element using element as the starting point. The resulting element will have the original element's props with the new props merged in shallowly. New children will replace existing children. key and ref from the original element will be preserved.

+ +

React.cloneElement() is almost equivalent to:

+
<element.type {...element.props} {...props}>{children}</element.type>
+
+

However, it also preserves refs. This means that if you get a child with a ref on it, you won't accidentally steal it from your ancestor. You will get the same ref attached to your new element.

+ +

This API was introduced as a replacement of the deprecated React.addons.cloneWithProps().

+ +
+

createFactory() #

React.createFactory(type)
+
+

Return a function that produces React elements of a given type. Like React.createElement(), the type argument can be either an html tag name string (eg. 'div', 'span', etc), or a React class.

+ +

You will not typically invoke React.createFactory() directly if you are using JSX. See React Without JSX to learn more.

+ +
+

isValidElement() #

React.isValidElement(object)
+
+

Verifies the object is a React element. Returns true or false.

+ +
+

React.Children #

+

React.Children provides utilities for dealing with the this.props.children opaque data structure.

+

React.Children.map #

React.Children.map(children, function[(thisArg)])
+
+

Invokes a function on every immediate child contained within children with this set to thisArg. If children is a keyed fragment or array it will be traversed: the function will never be passed the container objects. If children is null or undefined, returns null or undefined rather than an array.

+

React.Children.forEach #

React.Children.forEach(children, function[(thisArg)])
+
+

Like React.Children.map() but does not return an array.

+

React.Children.count #

Children.count(children)
+
+

Returns the total number of components in children, equal to the number of times that a callback passed to map or forEach would be invoked.

+

React.Children.only #

React.Children.only(children)
+
+

Returns the only child in children. Throws otherwise.

+

React.Children.toArray #

React.Children.toArray(children)
+
+

Returns the children opaque data structure as a flat array with keys assigned to each child. Useful if you want to manipulate collections of children in your render methods, especially if you want to reorder or slice this.props.children before passing it down.

+ +
+

Note:

+ +

React.Children.toArray() changes keys to preserve the semantics of nested arrays when flattening lists of children. That is, toArray prefixes each key in the returned array so that each element's key is scoped to the input array containing it.

+
+ +
+

React.PropTypes #

+

React.PropTypes exports a range of validators that can be used with a component's propTypes object to validate props being passed to your components.

+ +

For more information about PropTypes, see Typechecking with PropTypes.

+

React.PropTypes.array #

React.PropTypes.array
+
+

Validates that a prop is a JavaScript array primitive.

+

React.PropTypes.bool #

React.PropTypes.bool
+
+

Validates that a prop is a JavaScript bool primitive.

+

React.PropTypes.func #

React.PropTypes.func
+
+

Validates that a prop is a JavaScript function.

+

React.PropTypes.number #

React.PropTypes.number
+
+

Validates that a prop is a JavaScript number primitive.

+

React.PropTypes.object #

React.PropTypes.object
+
+

Validates that a prop is a JavaScript object.

+

React.PropTypes.string #

React.PropTypes.string
+
+

Validates that a prop is a JavaScript string primitive.

+

React.PropTypes.symbol #

React.PropTypes.symbol
+
+

Validates that a prop is a JavaScript symbol.

+

React.PropTypes.node #

React.PropTypes.node
+
+

Validates that a prop is anything that can be rendered: numbers, strings, elements or an array (or fragment) containing these types.

+

React.PropTypes.element #

React.PropTypes.element
+
+

Validates that a prop is a React element.

+

React.PropTypes.instanceOf() #

React.PropTypes.instanceOf(class)
+
+

Validates that a prop is an instance of a class. This uses JavaScript's instanceof operator.

+

React.PropTypes.oneOf() #

React.PropTypes.oneOf(arrayOfValues)
+
+

Validates that a prop is limited to specific values by treating it as an enum.

+
MyComponent.propTypes = {
+  optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
+}
+

React.PropTypes.oneOfType() #

React.PropTypes.oneOfType(arrayOfPropTypes)
+
+

Validates that a prop is an object that could be one of many types.

+
MyComponent.propTypes = {
+  optionalUnion: React.PropTypes.oneOfType([
+    React.PropTypes.string,
+    React.PropTypes.number,
+    React.PropTypes.instanceOf(Message)
+  ]),
+}
+

React.PropTypes.arrayOf() #

React.PropTypes.arrayOf(propType)
+
+

Validates that a prop is an an array of a certain type.

+
MyComponent.propTypes = {
+  optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
+}
+

React.PropTypes.objectOf() #

React.PropTypes.objectOf(propType)
+
+

Validates that a prop is an object with property values of a certain type.

+
MyComponent.propTypes = {
+  optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
+}
+

React.PropTypes.shape() #

React.PropTypes.shape(object)
+
+

Validates that a prop is an object taking on a particular shape.

+
MyComponent.propTypes = {
+  optionalObjectWithShape: React.PropTypes.shape({
+    color: React.PropTypes.string,
+    fontSize: React.PropTypes.number
+  }),
+}
+

React.PropTypes.any #

React.PropTypes.any
+
+

Validates that a prop has a value of any data type. Usually followed by isRequired.

+
MyComponent.propTypes = {
+  requiredAny: React.PropTypes.any.isRequired,
+}
+

isRequired #

propType.isRequired
+
+

You can chain any of the above validators with isRequired to make sure a warning is shown if the prop is not provided.

+
MyComponent.propTypes = {
+  requiredFunc: React.PropTypes.func.isRequired,
+}
+
+
+

React.addons #

React.addons
+
+

React.addons exports a range of add-ons when using react-with-addons.js.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/react-component.html b/docs/react-component.html new file mode 100644 index 0000000000..ba0d7006f6 --- /dev/null +++ b/docs/react-component.html @@ -0,0 +1,643 @@ + + + + + + + + + React.Component - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ React.Component +

+
+ +

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. React.Component is provided by React.

+

Overview #

+

React.Component is an abstract base class, so it rarely makes sense to refer to React.Component directly. Instead, you will typically subclass it, and define at least a render() method.

+ +

Normally you would define a React component as a plain JavaScript class:

+
class Greeting extends React.Component {
+  render() {
+    return <h1>Hello, {this.props.name}</h1>;
+  }
+}
+
+

If you don't use ES6 yet, you may use the React.createClass helper instead. Take a look at Using React without ES6 to learn more.

+

The Component Lifecycle #

+

Each component has several "lifecycle methods" that you can override to run code at particular times in the process. Methods prefixed with will are called right before something happens, and methods prefixed with did are called right after something happens.

+

Mounting #

+

These methods are called when an instance of a component is being created and inserted into the DOM:

+ + +

Updating #

+

An update can be caused by changes to props or state. These methods are called when a component is being re-rendered:

+ + +

Unmounting #

+

This method is called when a component is being removed from the DOM:

+ + +

Other APIs #

+

Each component also provides some other APIs:

+ + +

Class Properties #

+ +

Instance Properties #

+ + +
+

Reference #

render() #

render()
+
+

The render() method is required.

+ +

When called, it should examine this.props and this.state and return a single React element. This element can be either a representation of a native DOM component, such as <div />, or another composite component that you've defined yourself.

+ +

You can also return null or false to indicate that you don't want anything rendered. When returning null or false, ReactDOM.findDOMNode(this) will return null.

+ +

The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it's invoked, and it does not directly interact with the browser. If you need to interact with the browser, perform your work in componentDidMount() or the other lifecycle methods instead. Keeping render() pure makes components easier to think about.

+ +
+

Note

+ +

render() will not be invoked if shouldComponentUpdate() returns false.

+
+ +
+

constructor() #

constructor(props)
+
+

The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.

+ +

The constructor is the right place to initialize state. If you don't initialize state and you don't bind methods, you don't need to implement a constructor for your React component.

+ +

It's okay to initialize state based on props if you know what you're doing. Here's an example of a valid React.Component subclass constructor:

+
constructor(props) {
+  super(props);
+  this.state = {
+    color: props.initialColor
+  };
+}  
+
+

Beware of this pattern, as it effectively "forks" the props and can lead to bugs. Instead of syncing props to state, you often want to lift the state up.

+ +

If you "fork" props by using them for state, you might also want to implement componentWillReceiveProps(nextProps) to keep the state up-to-date with them. But lifting state up is often easier and less bug-prone.

+ +
+

componentWillMount() #

componentWillMount()
+
+

componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state in this method will not trigger a re-rendering. Avoid introducing any side-effects or subscriptions in this method.

+ +

This is the only lifecycle hook called on server rendering. Generally, we recommend using the constructor() instead.

+ +
+

componentDidMount() #

componentDidMount()
+
+

componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.

+ +
+

componentWillReceiveProps() #

componentWillReceiveProps(nextProps)
+
+

componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.

+ +

Note that React may call this method even if the props have not changed, so make sure to compare the current and next values if you only want to handle changes. This may occur when the parent component causes your component to re-render.

+ +

componentWillReceiveProps() is not invoked if you just call this.setState()

+ +
+

shouldComponentUpdate() #

shouldComponentUpdate(nextProps, nextState)
+
+

Use shouldComponentUpdate() to let React know if a component's output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior.

+ +

shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true This method is not called for the initial render or when forceUpdate() is used.

+ +

Returning false does not prevent child components from re-rendering when their state changes.

+ +

Currently, if shouldComponentUpdate() returns false, then componentWillUpdate(), render(), and componentDidUpdate() will not be invoked. Note that in the future React may treat shouldComponentUpdate() as a hint rather than a strict directive, and returning false may still result in a re-rendering of the component.

+ +

If you determine a specific component is slow after profiling, you may change it to inherit from React.PureComponent which implements shouldComponentUpdate() with a shallow prop and state comparison. If you are confident you want to write it by hand, you may compare this.props with nextProps and this.state with nextState and return false to tell React the update can be skipped.

+ +
+

componentWillUpdate() #

componentWillUpdate(nextProps, nextState)
+
+

componentWillUpdate() is invoked immediately before rendering when new props or state are being received. Use this as an opportunity to perform preparation before an update occurs. This method is not called for the initial render.

+ +

Note that you cannot call this.setState() here. If you need to update state in response to a prop change, use componentWillReceiveProps() instead.

+ +
+

Note

+ +

componentWillUpdate() will not be invoked if shouldComponentUpdate() returns false.

+
+ +
+

componentDidUpdate() #

componentDidUpdate(prevProps, prevState)
+
+

componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render.

+ +

Use this as an opportunity to operate on the DOM when the component has been updated. This is also a good place to do network requests as long as you compare the current props to previous props (e.g. a network request may not be necessary if the props have not changed).

+ +
+

Note

+ +

componentDidUpdate() will not be invoked if shouldComponentUpdate() returns false.

+
+ +
+

componentWillUnmount() #

componentWillUnmount()
+
+

componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. Perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any DOM elements that were created in componentDidMount

+ +
+

setState() #

setState(nextState, callback)
+
+

Performs a shallow merge of nextState into current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks.

+ +

The first argument can be an object (containing zero or more keys to update) or a function (of state and props) that returns an object containing keys to update.

+ +

Here is the simple object usage:

+
this.setState({mykey: 'my new value'});
+
+

It's also possible to pass a function with the signature function(state, props) => newState. This enqueues an atomic update that consults the previous value of state and props before setting any values. For instance, suppose we wanted to increment a value in state by props.step:

+
this.setState((prevState, props) => {
+  return {myInteger: prevState.myInteger + props.step};
+});
+
+

The second parameter is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.

+ +

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

+ +

There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

+ +

setState() will always lead to a re-render unless shouldComponentUpdate() returns false. If mutable objects are being used and conditional rendering logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.

+ +
+

forceUpdate() #

component.forceUpdate(callback)
+
+

By default, when your component's state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate().

+ +

Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child. React will still only update the DOM if the markup changes.

+ +

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().

+ +
+

Class Properties #

defaultProps #

+

defaultProps can be defined as a property on the component class itself, to set the default props for the class. This is used for undefined props, but not for null props. For example:

+
class CustomButton extends React.Component {
+  // ...
+}
+
+CustomButton.defaultProps = {
+  color: 'blue'
+};
+
+

If props.color is not provided, it will be set by default to 'blue':

+
  render() {
+    return <CustomButton /> ; // props.color will be set to blue
+  }
+
+

If props.color is set to null, it will remain null:

+
  render() {
+    return <CustomButton color={null} /> ; // props.color will remain null
+  }
+
+
+

displayName #

+

The displayName string is used in debugging messages. JSX sets this value automatically; see JSX in Depth.

+ +
+

propTypes #

+

propTypes can be defined as a property on the component class itself, to define what types the props should be. It should be a map from prop names to types as defined in React.PropTypes. In development mode, when an invalid value is provided for a prop, a warning will be shown in the JavaScript console. In production mode, propTypes checks are skipped for efficiency.

+ +

For example, this code ensures that the color prop is a string:

+
class CustomButton extends React.Component {
+  // ...
+}
+
+CustomButton.propTypes = {
+  name: React.PropTypes.string
+};
+
+

We recommend using Flow when possible, to get compile-time typechecking instead of runtime typechecking. Flow has built-in support for React so it's easy to run static analysis on a React app.

+ +
+

Instance Properties #

props #

+

this.props contains the props that were defined by the caller of this component. See Components and Props for an introduction to props.

+ +

In particular, this.props.children is a special prop, typically defined by the child tags in the JSX expression rather than in the tag itself.

+

state #

+

The state contains data specific to this component that may change over time. The state is user-defined, and it should be a plain JavaScript object.

+ +

If you don't use it in `render(), it shouldn't be on the state. For example, you can put timer IDs directly on the instance.

+ +

See State and Lifecycle for more information about the state.

+ +

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/react-dom-server.html b/docs/react-dom-server.html new file mode 100644 index 0000000000..a41d530b17 --- /dev/null +++ b/docs/react-dom-server.html @@ -0,0 +1,419 @@ + + + + + + + + + ReactDOMServer - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ ReactDOMServer +

+
+ +

If you use React as a script tag, these top-level APIs are available on the ReactDOMServer global. If you use ES6 with npm, you can write import ReactDOMServer from 'react-dom/server'. If you use ES5 with npm, you can write var ReactDOMServer = require('react-dom/server').

+

Overview #

+

The ReactDOMServer class allows you to render your components on the server.

+ + + +
+

Reference #

renderToString() #

ReactDOMServer.renderToString(element)
+
+

Render a React element to its initial HTML. This should only be used on the server. React will return an HTML string. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.

+ +

If you call ReactDOM.render() on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.

+ +
+

renderToStaticMarkup() #

ReactDOMServer.renderToStaticMarkup(element)
+
+

Similar to renderToString, except this doesn't create extra DOM attributes such as data-reactid, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/react-dom.html b/docs/react-dom.html new file mode 100644 index 0000000000..463147bbcc --- /dev/null +++ b/docs/react-dom.html @@ -0,0 +1,461 @@ + + + + + + + + + ReactDOM - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ ReactDOM +

+
+ +

If you use React as a script tag, these top-level APIs are available on the ReactDOM global. If you use ES6 with npm, you can write import ReactDOM from 'react-dom'. If you use ES5 with npm, you can write var ReactDOM = require('react-dom').

+

Overview #

+

The react-dom package provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.

+ + +

Browser Support #

+

React supports all popular browsers, including Internet Explorer 9 and above.

+ +
+

Note

+ +

We don't support older browsers that don't support ES5 methods, but you may find that your apps do work in older browsers if polyfills such as es5-shim and es5-sham are included in the page. You're on your own if you choose to take this path.

+
+ +
+

Reference #

render() #

ReactDOM.render(
+  element,
+  container,
+  [callback]
+)
+
+

Render a React element into the DOM in the supplied container and return a reference to the component (or returns null for stateless components.

+ +

If the React element was previously rendered into container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React element.

+ +

If the optional callback is provided, it will be executed after the component is rendered or updated.

+ +
+

Note:

+ +

ReactDOM.render() controls the contents of the container node you pass in. Any existing DOM elements inside are replaced when first called. Later calls use React’s DOM diffing algorithm for efficient updates.

+ +

ReactDOM.render() does not modify the container node (only modifies the children of the container). It may be possible to insert a component to an existing DOM node without overwriting the existing children.

+ +

ReactDOM.render() currently returns a reference to the root ReactComponent instance. However, using this return value is legacy +and should be avoided because future versions of React may render components asynchronously in some cases. If you need a reference to the root ReactComponent instance, the preferred solution is to attach a +callback ref to the root element.

+
+ +
+

unmountComponentAtNode() #

ReactDOM.unmountComponentAtNode(container)
+
+

Remove a mounted React component from the DOM and clean up its event handlers and state. If no component was mounted in the container, calling this function does nothing. Returns true if a component was unmounted and false if there was no component to unmount.

+ +
+

findDOMNode() #

ReactDOM.findDOMNode(component)
+
+

If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements. In most cases, you can attach a ref to the DOM node and avoid using findDOMNode at all. When render returns null or false, findDOMNode returns null.

+ +
+

Note:

+ +

findDOMNode is an escape hatch used to access the underlying DOM node. In most cases, use of this escape hatch is discouraged because it pierces the component abstraction.

+ +

findDOMNode only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like calling findDOMNode() in render() on a component that has yet to be created) an exception will be thrown.

+ +

findDOMNode cannot be used on functional components.

+
+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/react-without-es6.html b/docs/react-without-es6.html new file mode 100644 index 0000000000..5fdb25c3cb --- /dev/null +++ b/docs/react-without-es6.html @@ -0,0 +1,578 @@ + + + + + + + + + React Without ES6 - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ React Without ES6 +

+
+ +

Normally you would define a React component as a plain JavaScript class:

+
class Greeting extends React.Component {
+  render() {
+    return <h1>Hello, {this.props.name}</h1>;
+  }
+}
+
+

If you don't use ES6 yet, you may use the React.createClass helper instead:

+
var Greeting = React.createClass({
+  render: function() {
+    return <h1>Hello, {this.props.name}</h1>;
+  }
+});
+
+

The API of ES6 classes is similar to React.createClass with a few exceptions.

+

Declaring Prop Types and Default Props #

+

With functions and ES6 classes, propTypes and defaultProps are defined as properties on the components themselves:

+
class Greeting extends React.Component {
+  // ...
+}
+
+Greeting.propTypes = {
+  name: React.PropTypes.string
+};
+
+Greeting.defaultProps = {
+  name: 'Mary'
+};
+
+

With React.createClass(), you need to define propTypes as a property on the passed object, and getDefaultProps() as a function on it:

+
var Greeting = React.createClass({
+  propTypes: {
+    name: React.PropTypes.string
+  },
+
+  getDefaultProps: function() {
+    return {
+      name: 'Mary'
+    };
+  },
+
+  // ...
+
+});
+

Setting the Initial State #

+

In ES6 classes, you can define the initial state by assigning this.state in the constructor:

+
class Counter extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {count: props.initialCount};
+  }
+  // ...
+}
+
+

With React.createClass(), you have to provide a separate getInitialState method that returns the initial state:

+
var Counter = React.createClass({
+  getInitialState: function() {
+    return {count: this.props.initialCount};
+  },
+  // ...
+});
+

Autobinding #

+

In React components declared as ES6 classes, methods follow the same semantics as regular ES6 classes. This means that they don't automatically bind this to the instance. You'll have to explicitly use .bind(this) in the constructor:

+
class SayHello extends React.Component {
+  constructor(props) {
+    super(props);
+    // This line is important!
+    this.handleClick = this.handleClick.bind(this);
+  }
+
+  handleClick() {
+    alert('Hello!');
+  }
+
+  render() {
+    // Because `this.handleClick` is bound, we can use it as an event handler.
+    return (
+      <button onClick={this.handleClick}>
+        Say hello
+      </button>
+    );
+  }
+}
+
+

With React.createClass(), this is not necessary because it binds all methods:

+
var SayHello = React.createClass({
+  handleClick: function() {
+    alert('Hello!');
+  },
+
+  render: function() {
+    return (
+      <button onClick={this.handleClick}>
+        Say hello
+      </button>
+    );
+  }
+});
+
+

This means writing ES6 classes comes with a little more boilerplate code for event handlers, but the upside is slightly better performance in large applications.

+ +

If the boilerplate code is too unattractive to you, you may enable the experimental Class Properties syntax proposal with Babel:

+
class SayHello extends React.Component {
+  // WARNING: this syntax is experimental!
+  // Using an arrow here binds the method:
+  handleClick = () => {
+    alert('Hello!');
+  }
+
+  render() {
+    return (
+      <button onClick={this.handleClick}>
+        Say hello
+      </button>
+    );
+  }
+}
+
+

Please note that the syntax above is experimental and the syntax may change, or the proposal might not make it into the language.

+ +

If you'd rather play it safe, you have a few options:

+ +
    +
  • Bind methods in the constructor.
  • +
  • Use arrow functions, e.g. onClick={(e) => this.handleClick(e)}).
  • +
  • Keep using React.createClass().
  • +
+

Mixins #

+
+

Note:

+ +

ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes.

+ +

We also found numerous issues in codebases using mixins, and don't recommend using them in the new code.

+ +

This section exists only for the reference.

+
+ +

Sometimes very different components may share some common functionality. These are sometimes called cross-cutting concerns. React.createClass lets you use a legacy mixins system for that.

+ +

One common use case is a component wanting to update itself on a time interval. It's easy to use setInterval(), but it's important to cancel your interval when you don't need it anymore to save memory. React provides lifecycle methods that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy setInterval() function that will automatically get cleaned up when your component is destroyed.

+
var SetIntervalMixin = {
+  componentWillMount: function() {
+    this.intervals = [];
+  },
+  setInterval: function() {
+    this.intervals.push(setInterval.apply(null, arguments));
+  },
+  componentWillUnmount: function() {
+    this.intervals.forEach(clearInterval);
+  }
+};
+
+var TickTock = React.createClass({
+  mixins: [SetIntervalMixin], // Use the mixin
+  getInitialState: function() {
+    return {seconds: 0};
+  },
+  componentDidMount: function() {
+    this.setInterval(this.tick, 1000); // Call a method on the mixin
+  },
+  tick: function() {
+    this.setState({seconds: this.state.seconds + 1});
+  },
+  render: function() {
+    return (
+      <p>
+        React has been running for {this.state.seconds} seconds.
+      </p>
+    );
+  }
+});
+
+ReactDOM.render(
+  <TickTock />,
+  document.getElementById('example')
+);
+
+

If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/react-without-jsx.html b/docs/react-without-jsx.html new file mode 100644 index 0000000000..0c2277c67e --- /dev/null +++ b/docs/react-without-jsx.html @@ -0,0 +1,436 @@ + + + + + + + + + React Without JSX - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ React Without JSX +

+
+ +

JSX is not a requirement for using React. Using React without JSX is especially convenient when you don't want to set up compilation in your build environment.

+ +

Each JSX element is just syntactic sugar for calling React.createElement(component, props, ...children). So, anything you can do with JSX can also be done with just plain JavaScript.

+ +

For example, this code written with JSX:

+
class Hello extends React.Component {
+  render() {
+    return <div>Hello {this.props.toWhat}</div>;
+  }
+}
+
+ReactDOM.render(
+  <Hello toWhat="World" />,
+  document.getElementById('root')
+);
+
+

can be compiled to this code that does not use JSX:

+
class Hello extends React.Component {
+  render() {
+    return React.createElement('div', null, `Hello ${this.props.toWhat}`);
+  }
+}
+
+ReactDOM.render(React.createElement(Hello, {toWhat: 'World'}, null),
+                document.getElementById('root'));
+
+

If you're curious to see more examples of how JSX is converted to JavaScript, you can try out the online Babel compiler.

+ +

The component can either be provided as a string, or as a subclass of React.Component, or a plain function for stateless components.

+ +

If you get tired of typing React.createElement so much, one common pattern is to assign a shorthand:

+
var e = React.createElement;
+
+ReactDOM.render(e('div', null, 'Hello World'),
+                document.getElementById('root'));
+
+

If you use this shorthand form for React.createElement, it can be almost as convenient to use React without JSX.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/reconciliation-it-IT.html b/docs/reconciliation-it-IT.html deleted file mode 100644 index 503e229f3e..0000000000 --- a/docs/reconciliation-it-IT.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - Riconciliazione | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Riconciliazione -

-
- -

La decisione chiave del design di React è fare in modo che l'API sembri ripetere il rendering dell'intera applicazione per ciascun aggiornamento. Ciò rende la scrittura delle applicazione molto più semplice, ma è anche una sfida incredibile per renderlo trattabile. Questo articolo spiega come siamo riusciti a trasformare, tramite potenti euristiche, un problema O(n3) in uno O(n).

-

Motivazione #

-

Generare il minimo numero di operazioni necessarie a trasformare un albero in un altro è un problema complesso e ben noto. Gli algoritmi dello stato dell'arte hanno una complessità dell'ordine di O(n3) dove n è il numero di nodi dell'albero.

- -

Ciò significa che visualizzare 1000 nodi richiederebbe un numero di confronti dell'ordine del miliardo. Ciò è decisamente troppo costoso per il nostro caso d'uso. Per mettere questo numero in prospettiva, le CPU oggi giorno eseguono approssimativamente 3 miliardi di istruzioni al secondo. Quindi anche con l'implementazione più efficiente, non saremmo in grado di calcolare la differenza in meno di un secondo.

- -

Dal momento che un algoritmo ottimo non è trattabile, implementiamo un algoritmo O(n) non ottimale usando euristiche basate su due assunzioni:

- -
    -
  1. Due componenti della stessa classe genereranno alberi simili e due componenti di classi diverse genereranno alberi diversi.
  2. -
  3. È possibile fornire una chiave unica per gli elementi che sia stabile durante rendering differenti.
  4. -
- -

In pratica, queste assunzioni sono eccezionalmente veloci per quasi tutti i casi d'uso pratici.

-

Differenza a coppie #

-

Per effettuare la differenza di due alberi, dobbiamo prima essere capaci di effettuare la differenza tra due nodi. Esistono tre diversi casi da considerare.

-

Tipi di Nodo Differenti #

-

Se il tipo di nodo è differente, React li tratterà come due sottoalberi diversi, getterà via il primo e costruirà e inserirà il secondo.

-
renderA: <div />
-renderB: <span />
-=> [removeNode <div />], [insertNode <span />]
-
-

La stessa logica è usata per i componenti personalizzati. Se non sono dello stesso tipo, React non proverà neppure a confrontare ciò che visualizzano. Rimuoverà soltanto il primo dal DOM e inserirà il secondo.

-
renderA: <Header />
-renderB: <Content />
-=> [removeNode <Header />], [insertNode <Content />]
-
-

Possedere questa conoscenza di alto livello è un aspetto molto importante del perché l'algoritmo di differenza di React è sia veloce che preciso. Ciò fornisce una buona euristica per potare rapidamente gran parte dell'albero e concentrarsi su parti che hanno una buona probabilità di essere simili.

- -

È molto improbabile che un elemento <Header> generi un DOM che somigli a quello generato da un elemento <Content>. Anziché perdere tempo provando a confrontare queste due strutture, React semplicemente ricostruisce l'albero da zero.

- -

Come corollario, se c'è un elemento <Header> nella stessa posizione in due rendering consecutivi, ti puoi aspettare di trovare una struttura molto simile che vale la pena di esplorare.

-

Nodi DOM #

-

Quando vengono confrontati nodi DOM, guardiamo gli attributi di entrambi e decidiamo quali di essi sono cambiati in un tempo lineare.

-
renderA: <div id="before" />
-renderB: <div id="after" />
-=> [replaceAttribute id "after"]
-
-

Anziché trattare lo stile come una stringa opaca, viene rappresentato come un oggetto chiave-valore. Ciò ci permette di aggiornare solo le proprietà che sono cambiate.

-
renderA: <div style={{color: 'red'}} />
-renderB: <div style={{fontWeight: 'bold'}} />
-=> [removeStyle color], [addStyle font-weight 'bold']
-
-

Dopo che gli attributi sono stati aggiornati, effettuiamo un confronto ricorsivo su ciascuno dei nodi figli.

-

Componenti Personalizzati #

-

We decided that the two custom components are the same. Since components are stateful, we cannot just use the new component and call it a day. React takes all the attributes from the new component and calls component[Will/Did]ReceiveProps() on the previous one.

- -

The previous component is now operational. Its render() method is called and the diff algorithm restarts with the new result and the previous result.

-

List-wise diff #

Problematic Case #

-

In order to do children reconciliation, React adopts a very naive approach. It goes over both lists of children at the same time and generates a mutation whenever there's a difference.

- -

For example if you add an element at the end:

-
renderA: <div><span>first</span></div>
-renderB: <div><span>first</span><span>second</span></div>
-=> [insertNode <span>second</span>]
-
-

Inserting an element at the beginning is problematic. React is going to see that both nodes are spans and therefore run into a mutation mode.

-
renderA: <div><span>first</span></div>
-renderB: <div><span>second</span><span>first</span></div>
-=> [replaceAttribute textContent 'second'], [insertNode <span>first</span>]
-
-

There are many algorithms that attempt to find the minimum sets of operations to transform a list of elements. Levenshtein distance can find the minimum using single element insertion, deletion and substitution in O(n2). Even if we were to use Levenshtein, this doesn't find when a node has moved into another position and algorithms to do that have much worse complexity.

-

Keys #

-

In order to solve this seemingly intractable issue, an optional attribute has been introduced. You can provide for each child a key that is going to be used to do the matching. If you specify a key, React is now able to find insertion, deletion, substitution and moves in O(n) using a hash table.

-
renderA: <div><span key="first">first</span></div>
-renderB: <div><span key="second">second</span><span key="first">first</span></div>
-=> [insertNode <span>second</span>]
-
-

In practice, finding a key is not really hard. Most of the time, the element you are going to display already has a unique id. When that's not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. Remember that the key only has to be unique among its siblings, not globally unique.

-

Trade-offs #

-

It is important to remember that the reconciliation algorithm is an implementation detail. React could re-render the whole app on every action; the end result would be the same. We are regularly refining the heuristics in order to make common use cases faster.

- -

In the current implementation, you can express the fact that a sub-tree has been moved amongst its siblings, but you cannot tell that it has moved somewhere else. The algorithm will re-render that full sub-tree.

- -

Because we rely on two heuristics, if the assumptions behind them are not met, performance will suffer.

- -
    -
  1. The algorithm will not try to match sub-trees of different components classes. If you see yourself alternating between two components classes with very similar output, you may want to make it the same class. In practice, we haven't found this to be an issue.

  2. -
  3. If you don't provide stable keys (by using Math.random() for example), all the sub-trees are going to be re-rendered every single time. By giving the users the choice to choose the key, they have the ability to shoot themselves in the foot.

  4. -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/reconciliation-ko-KR.html b/docs/reconciliation-ko-KR.html deleted file mode 100644 index b01c4be6d3..0000000000 --- a/docs/reconciliation-ko-KR.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - 비교조정(Reconciliation) | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 비교조정(Reconciliation) -

-
- -

React의 주요 설계 철학은 업데이트할 때마다 전체 앱을 다시 렌더하는 것처럼 보이게 API를 만드는 것입니다. 이렇게 하면 애플리케이션 작성이 훨씬 쉬워지지만 한편으로는 어려운 도전 과제이기도 합니다. 이 글에서는 강력한 휴리스틱으로 어떻게 O(n3) 복잡도의 문제를 O(n)짜리로 바꿀 수 있었는지 설명합니다.

-

동기 #

-

최소한의 연산으로 어떤 트리를 다른 트리로 바꾸는 것은 복잡하고 많이 연구된 문제입니다. n을 트리에 있는 노드 수라고 할 때 최신 알고리즘은 O(n3) 복잡도를 가집니다.

- -

다시 말해 1000개의 노드를 표시하려면 10억 번 수준의 비교를 해야 한다는 뜻입니다. 이는 우리가 필요한 용도로는 너무 비쌉니다. 이 수치를 좀 더 알기 쉽게 설명하면, 요즘 CPU는 1초에 대략 30억 번의 연산을 하므로 가장 빠른 구현으로도 1초 안에 이러한 비교는 계산해낼 수 없다는 것입니다.

- -

최적의 알고리즘을 사용할 수 없기 때문에, 완전하진 않지만 다음의 두 가지 가정에 기반한 휴리스틱을 사용한 O(n) 알고리즘으로 구현했습니다.

- -
    -
  1. 같은 클래스의 두 컴포넌트는 비슷한 트리를 생성하고, 서로 다른 클래스를 가진 두 컴포넌트는 서로 다른 트리를 생성할 것이다.
  2. -
  3. 각 렌더 과정들 사이에 유지되는 엘리먼트에 고유한 키를 제공할 수 있다.
  4. -
- -

실제로 이러한 가정은 거의 모든 실용적인 상황에서 굉장히 빠릅니다.

-

일대일 비교 #

-

트리 비교를 하기 위해서는 먼저 두 노드를 비교할 수 있어야 합니다. 세 가지 경우를 다룹니다.

-

서로 다른 노드 타입 #

-

두 노드의 타입이 서로 다르다면, React는 이를 두 개의 서로 다른 서브트리로 간주해 처음 것을 버리고 두번째 것을 만들어 삽입합니다.

-
renderA: <div />
-renderB: <span />
-=> [removeNode <div />], [insertNode <span />]
-
-

동일한 로직이 커스텀 컴포넌트에 대해서도 적용됩니다. 타입이 다르다면 React는 그 컴포넌트들이 무엇을 렌더하는지 조차도 비교하지 않습니다. 그저 처음 것을 DOM에서 제거하고 두번째 것을 삽입합니다.

-
renderA: <Header />
-renderB: <Content />
-=> [removeNode <Header />], [insertNode <Content />]
-
-

이러한 고수준의 사실을 알 수 있다는 것이 React의 비교 알고리즘이 빠르면서 정확할 수 있는 비결입니다. 트리의 커다란 부분을 일찌감치 탐색 대상에서 제외하고 비슷할 가능성이 높은 부분에 집중할 수 있는 좋은 휴리스틱을 제공합니다.

- -

<Header> 엘리먼트가 생성하는 DOM이 <Content>가 생성하는 것과 비슷하게 생길 확률은 매우 낮습니다. 이 두 구조를 비교하는데 시간을 낭비하지 않고 React는 그냥 트리를 처음부터 새로 만듭니다.

- -

한편 두 번의 연속적인 렌더에서 같은 위치에 <Header> 엘리먼트가 있다면 비슷한 구조일 것이므로 탐색할만 합니다.

-

DOM 노드 #

-

두 DOM 노드를 비교할 때는 어트리뷰트를 보고 무엇이 바뀌었는지 선형 시간 안에 결정할 수 있습니다.

-
renderA: <div id="before" />
-renderB: <div id="after" />
-=> [replaceAttribute id "after"]
-
-

스타일을 불명확한 문자열로 다루지 않고 키-값 객체를 사용합니다. 이는 변경된 프로퍼티만 업데이트 하도록 해줍니다.

-
renderA: <div style={{color: 'red'}} />
-renderB: <div style={{fontWeight: 'bold'}} />
-=> [removeStyle color], [addStyle font-weight 'bold']
-
-

어트리뷰트가 업데이트된 다음에는, 모든 자식도 재귀적으로 업데이트합니다.

-

커스텀 컴포넌트 #

-

우리는 두 커스텀 컴포넌트를 같은 것으로 취급하기로 했습니다. 컴포넌트는 상태를 가지기 때문에 새 컴포넌트를 그냥 사용할 수는 없습니다. React는 새 컴포넌트의 모든 어트리뷰트를 취해 이전 컴포넌트의 component[Will/Did]ReceiveProps()를 호출해 줍니다.

- -

이제 이전 컴포넌트가 작동합니다. 거기 있는 render() 메소드가 호출되고 비교 알고리즘이 다시 새로운 결과와 이전 결과를 비교합니다.

-

목록끼리 비교 #

문제가 되는 경우 #

-

React는 매우 단순한 방식으로 자식 비교조정(children reconciliation)을 합니다. 자식 목록을 동시에 서로 비교하다가 차이를 발견하면 변경 사항을 적용합니다.

- -

예를 들어 맨 끝에 엘리먼트를 추가한 경우에는:

-
renderA: <div><span>first</span></div>
-renderB: <div><span>first</span><span>second</span></div>
-=> [insertNode <span>second</span>]
-
-

맨 앞에 엘리먼트를 삽입하는 경우가 문제입니다. React는 두 노드가 모두 span인지 확인하고 변경 모드로 작동합니다.

-
renderA: <div><span>first</span></div>
-renderB: <div><span>second</span><span>first</span></div>
-=> [replaceAttribute textContent 'second'], [insertNode <span>first</span>]
-
-

원소의 목록을 변환하기 위한 최소 연산 집합을 찾는 알고리즘이 여럿 있습니다. Levenshtein distance를 사용하면 O(n2) 복잡도로 원소 한 개의 삽입, 삭제, 교체를 위해 필요한 최솟값을 찾을 수 있습니다. Levenshtein 알고리즘을 사용해도 노드가 다른 위치로 이동한 경우는 알아낼 수 없고, 그것을 알아내는 알고리즘은 더욱 높은 복잡도를 가집니다.

-

키(keys) #

-

해결할 수 없어보이는 이 문제를 풀기 위해 선택적인 어트리뷰트를 도입했습니다. 각 자식에 키(key)를 할당해 이를 비교하는 데에 사용합니다. 키를 명시하면 React가 해시 테이블을 사용하여 삽입, 삭제, 교체 및 이동을 O(n) 복잡도로 찾아낼 수 있습니다.

-
renderA: <div><span key="first">first</span></div>
-renderB: <div><span key="second">second</span><span key="first">first</span></div>
-=> [insertNode <span>second</span>]
-
-

실제 상황에서 키를 찾는 것은 별로 어렵지 않습니다. 대부분의 경우, 표시하려는 엘리먼트는 이미 고유한 식별자를 가지고 있습니다. 그렇지 않은 경우에도 모델에 새로운 ID 프로퍼티를 추가하거나 내용의 일부분을 해시하여 키를 생성할 수 있습니다. 키는 형제 노드 사이에서만 고유하면 됩니다. 전역적으로 고유할 필요는 없습니다.

-

트레이드오프 #

-

비교조정 알고리즘이 구현 세부사항이라는 것을 기억하는 것은 중요합니다. React가 전체 앱을 모든 동작마다 새로 렌더해도 결과는 같을 것입니다. 일반적인 사용 패턴을 빠르게 만들 수 있도록 저희는 계속 휴리스틱을 다듬고 있습니다.

- -

현재 구현에서 서브트리가 형제 노드 사이에서 이동하는 경우는 표현할 수 있지만, 그 외의 곳으로 이동했는지는 알 수 없습니다. 알고리즘에 따라 전체 서브트리가 다시 렌더됩니다.

- -

두 가지 휴리스틱에 의존하기 때문에 그에 대한 가정이 만족되지 않으면 성능이 좋지 않을 것입니다.

- -
    -
  1. 서로 다른 컴포넌트 클래스의 서브트리는 비교하려고 시도하지 않습니다. 만약 매우 비슷한 출력 결과의 두 컴포넌트를 왔다갔다 하는 경우 같은 클래스로 만들 수 있습니다. 실제 상황에서는 큰 문제가 없습니다.

  2. -
  3. 안정적인 키를 붙이지 않을 경우 (예를 들어 Math.random()을 사용한다거나) 모든 서브트리가 매번 다시 렌더될 것입니다. 사용자에게 키를 선택하도록 하는 대신 실수할 수 있는 여지가 있습니다.

  4. -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/reconciliation.html b/docs/reconciliation.html index 70b8da1bf0..bf7747b3ea 100644 --- a/docs/reconciliation.html +++ b/docs/reconciliation.html @@ -1,12 +1,14 @@ + + - Reconciliation | React - - + Reconciliation - React + + @@ -44,31 +46,159 @@
-
+
+ Edit on GitHub +

+ Reconciliation +

+
+ +

React provides a declarative API so that you don't have to worry about exactly what changes on every update. This makes writing applications a lot easier, but it might not be obvious how this is implemented within React. This article explains the choices we made in React's "diffing" algorithm so that component updates are predictable while being fast enough for high-performance apps.

+

Motivation #

+

When you use React, at a single point in time you can think of the render() function as creating a tree of React elements. On the next state or props update, that render() function will return a different tree of React elements. React then needs to figure out how to efficiently update the UI to match the most recent tree.

+ +

There are some generic solutions to this algorithmic problem of generating the minimum number of operations to transform one tree into another. However, the state of the art algorithms have a complexity in the order of O(n3) where n is the number of elements in the tree.

+ +

If we used this in React, displaying 1000 elements would require in the order of one billion comparisons. This is far too expensive. Instead, React implements a heuristic O(n) algorithm based on two assumptions:

+ +
    +
  1. Two elements of different types will produce different trees.
  2. +
  3. The developer can hint at which child elements may be stable across different renders with a key prop.
  4. +
+ +

In practice, these assumptions are valid for almost all practical use cases.

+

The Diffing Algorithm #

+

When diffing two trees, React first compares the the two root elements. The behavior is different depending on the types of the root elements.

+

Elements Of Different Types #

+

Whenever the root elements have different types, React will tear down the old tree and build the new tree from scratch. Going from <a> to <img>, or from <Article> to <Comment>, or from <Button> to <div> - any of those will lead to a full rebuild.

+ +

When tearing down a tree, old DOM nodes are destroyed. Component instances receive componentWillUnmount(). When building up a new tree, new DOM nodes are inserted into the DOM. Component instances receive componentWillMount() and then componentDidMount(). Any state associated with the old tree is lost.

+ +

Any componts below the root will also get unmounted and have their state destroyed. For example, when diffing:

+
<div>
+  <Counter />
+</div>
+
+<span>
+  <Counter />
+</span>
+
+

This will destroy the old Counter and remount a new one.

+

DOM Elements Of The Same Type #

+

When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes. For example:

+
<div className="before" title="stuff" />
+
+<div className="after" title="stuff" />
+
+

By comparing these two elements, React knows to only modify the className on the underlying DOM node.

+ +

When updating style, React also knows to update only the properties that changed. For example:

+
<div style={{color: 'red', fontWeight: 'bold'}} />
+
+<div style={{color: 'green', fontWeight: 'bold'}} />
+
+

When converting between these two elements, React knows to only modify the color style, not the fontWeight.

+ +

After handling the DOM node, React then recurses on the children.

+

Component Elements Of The Same Type #

+

When a component updates, the instance stays the same, so that state is maintained across renders. React updates the props of the underlying component instance to match the new element, and calls componentWillReceiveProps() and componentWillUpdate() on the underlying instance.

+ +

Next, the render() method is called and the diff algorithm recurses on the previous result and the new result.

+

Recursing On Children #

+

By default, when recursing on the children of a DOM node, React just iterates over both lists of children at the same time and generates a mutation whenever there's a difference.

+ +

For example, when adding an element at the end of the children, converting between these two trees works well:

+
<ul>
+  <li>first</li>
+  <li>second</li>
+</ul>
+
+<ul>
+  <li>first</li>
+  <li>second</li>
+  <li>third</li>
+</ul>
+
+

React will match the two <li>first</li> trees, match the two <li>second</li> trees, and then insert the <li>third</li> tree.

+ +

If you implement it naively, inserting an element at the beginning has worse performance. For example, converting between these two trees works poorly:

+
<ul>
+  <li>Duke</li>
+  <li>Villanova</li>
+</ul>
+
+<ul>
+  <li>Connecticut</li>
+  <li>Duke</li>
+  <li>Villanova</li>
+</ul>
+
+

React will mutate every child instead of realizing it can keep the <li>Duke</li> and <li>Villanova</li> subtrees intact. This inefficiency can be a problem.

+

Keys #

+

In order to solve this issue, React supports a key attribute. When children have keys, React uses the key to match children in the original tree with children in the subsequent tree. For example, adding a key to our inefficient example above can make the tree conversion efficient:

+
<ul>
+  <li key="2015"}>Duke</li>
+  <li key="2016"}>Villanova</li>
+</ul>
+
+<ul>
+  <li key="2014"}>Connecticut</li>
+  <li key="2015"}>Duke</li>
+  <li key="2016"}>Villanova</li>
+</ul>
+
+

Now React knows that the element with key '2014' is the new one, and the elements with the keys '2015' and '2016' have just moved.

+ +

In practice, finding a key is usually not hard. The element you are going to display may already have a unique ID, so the key can just come from your data:

+
<li key={item.id}>{item.name}</li>
+
+

When that's not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. The key only has to be unique among its siblings, not globally unique.

+ +

As a last resort, you can pass item's index in the array as a key. This can work well if the items are never reordered, but reorders will be slow.

+

Tradeoffs #

+

It is important to remember that the reconciliation algorithm is an implementation detail. React could rerender the whole app on every action; the end result would be the same. We are regularly refining the heuristics in order to make common use cases faster.

+ +

In the current implementation, you can express the fact that a subtree has been moved amongst its siblings, but you cannot tell that it has moved somewhere else. The algorithm will rerender that full subtree.

+ +

Because React relies on heuristics, if the assumptions behind them are not met, performance will suffer.

+ +
    +
  1. The algorithm will not try to match subtrees of different component types. If you see yourself alternating between two component types with very similar output, you may want to make it the same type. In practice, we haven't found this to be an issue.

  2. +
  3. Keys should be stable, predictable, and unique. Unstable keys (like those produced by Math.random()) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.

  4. +
+ + +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,123 +433,57 @@
+ - -
- Edit on GitHub -

- Reconciliation -

-
- -

React's key design decision is to make the API seem like it re-renders the whole app on every update. This makes writing applications a lot easier but is also an incredible challenge to make it tractable. This article explains how with powerful heuristics we managed to turn a O(n3) problem into a O(n) one.

-

Motivation #

-

Generating the minimum number of operations to transform one tree into another is a complex and well-studied problem. The state of the art algorithms have a complexity in the order of O(n3) where n is the number of nodes in the tree.

- -

This means that displaying 1000 nodes would require in the order of one billion comparisons. This is far too expensive for our use case. To put this number in perspective, CPUs nowadays execute roughly 3 billion instructions per second. So even with the most performant implementation, we wouldn't be able to compute that diff in less than a second.

- -

Since an optimal algorithm is not tractable, we implement a non-optimal O(n) algorithm using heuristics based on two assumptions:

- -
    -
  1. Two components of the same class will generate similar trees and two components of different classes will generate different trees.
  2. -
  3. It is possible to provide a unique key for elements that is stable across different renders.
  4. -
- -

In practice, these assumptions are ridiculously fast for almost all practical use cases.

-

Pair-wise diff #

-

In order to do a tree diff, we first need to be able to diff two nodes. There are three different cases being handled.

-

Different Node Types #

-

If the node type is different, React is going to treat them as two different sub-trees, throw away the first one and build/insert the second one.

-
renderA: <div />
-renderB: <span />
-=> [removeNode <div />], [insertNode <span />]
-
-

The same logic is used for custom components. If they are not of the same type, React is not going to even try at matching what they render. It is just going to remove the first one from the DOM and insert the second one.

-
renderA: <Header />
-renderB: <Content />
-=> [removeNode <Header />], [insertNode <Content />]
-
-

Having this high level knowledge is a very important aspect of why React's diff algorithm is both fast and precise. It provides a good heuristic to quickly prune big parts of the tree and focus on parts likely to be similar.

- -

It is very unlikely that a <Header> element is going to generate a DOM that is going to look like what a <Content> would generate. Instead of spending time trying to match those two structures, React just re-builds the tree from scratch.

- -

As a corollary, if there is a <Header> element at the same position in two consecutive renders, you would expect to see a very similar structure and it is worth exploring it.

-

DOM Nodes #

-

When comparing two DOM nodes, we look at the attributes of both and can decide which of them changed in linear time.

-
renderA: <div id="before" />
-renderB: <div id="after" />
-=> [replaceAttribute id "after"]
-
-

Instead of treating style as an opaque string, a key-value object is used instead. This lets us update only the properties that changed.

-
renderA: <div style={{color: 'red'}} />
-renderB: <div style={{fontWeight: 'bold'}} />
-=> [removeStyle color], [addStyle font-weight 'bold']
-
-

After the attributes have been updated, we recurse on all the children.

-

Custom Components #

-

We decided that the two custom components are the same. Since components are stateful, we cannot just use the new component and call it a day. React takes all the attributes from the new component and calls componentWillReceiveProps() and componentWillUpdate() on the previous one.

- -

The previous component is now operational. Its render() method is called and the diff algorithm restarts with the new result and the previous result.

-

List-wise diff #

Problematic Case #

-

In order to do children reconciliation, React adopts a very naive approach. It goes over both lists of children at the same time and generates a mutation whenever there's a difference.

- -

For example if you add an element at the end:

-
renderA: <div><span>first</span></div>
-renderB: <div><span>first</span><span>second</span></div>
-=> [insertNode <span>second</span>]
-
-

Inserting an element at the beginning is problematic. React is going to see that both nodes are spans and therefore run into a mutation mode.

-
renderA: <div><span>first</span></div>
-renderB: <div><span>second</span><span>first</span></div>
-=> [replaceAttribute textContent 'second'], [insertNode <span>first</span>]
-
-

There are many algorithms that attempt to find the minimum sets of operations to transform a list of elements. Levenshtein distance can find the minimum using single element insertion, deletion and substitution in O(n2). Even if we were to use Levenshtein, this doesn't find when a node has moved into another position and algorithms to do that have much worse complexity.

-

Keys #

-

In order to solve this seemingly intractable issue, an optional attribute has been introduced. You can provide for each child a key that is going to be used to do the matching. If you specify a key, React is now able to find insertion, deletion, substitution and moves in O(n) using a hash table.

-
renderA: <div><span key="first">first</span></div>
-renderB: <div><span key="second">second</span><span key="first">first</span></div>
-=> [insertNode <span>second</span>]
-
-

In practice, finding a key is not really hard. Most of the time, the element you are going to display already has a unique id. When that's not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. Remember that the key only has to be unique among its siblings, not globally unique.

-

Trade-offs #

-

It is important to remember that the reconciliation algorithm is an implementation detail. React could re-render the whole app on every action; the end result would be the same. We are regularly refining the heuristics in order to make common use cases faster.

- -

In the current implementation, you can express the fact that a sub-tree has been moved amongst its siblings, but you cannot tell that it has moved somewhere else. The algorithm will re-render that full sub-tree.

- -

Because we rely on two heuristics, if the assumptions behind them are not met, performance will suffer.

- -
    -
  1. The algorithm will not try to match sub-trees of different components classes. If you see yourself alternating between two components classes with very similar output, you may want to make it the same class. In practice, we haven't found this to be an issue.

  2. -
  3. Keys should be stable, predictable, and unique. Unstable keys (like those produced by Math.random()) will cause many nodes to be unnecessarily re-created, which can cause performance degradation and lost state in child components.

  4. -
- - -
- - ← Prev - - - Next → - -
-
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
- -
+ + + +
- diff --git a/docs/reference-ko-KR.html b/docs/reference-ko-KR.html deleted file mode 100644 index 74ab3cf0c1..0000000000 --- a/docs/reference-ko-KR.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting… - - -

Redirecting…

-Click here if you are not redirected. - - diff --git a/docs/reference-zh-CN.html b/docs/reference-zh-CN.html deleted file mode 100644 index b9d6d8cfb3..0000000000 --- a/docs/reference-zh-CN.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting… - - -

Redirecting…

-Click here if you are not redirected. - - diff --git a/docs/reference.html b/docs/reference.html deleted file mode 100644 index e0ed2d697a..0000000000 --- a/docs/reference.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting… - - -

Redirecting…

-Click here if you are not redirected. - - diff --git a/docs/refs-and-the-dom.html b/docs/refs-and-the-dom.html new file mode 100644 index 0000000000..42d884948a --- /dev/null +++ b/docs/refs-and-the-dom.html @@ -0,0 +1,468 @@ + + + + + + + + + Refs and the DOM - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Refs and the DOM +

+
+ +

In the typical React dataflow, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props. However, there are a few cases where you need to imperatively modify a child outside of the typical dataflow. The child to be modified could be an instance of a React component, or it could be a DOM element. For both of these cases, React provides an escape hatch.

+

The ref Callback Attribute #

+

React supports a special attribute that you can attach to any component. The ref attribute takes a callback function, and the callback will be executed immediately after the component is mounted or unmounted.

+ +

When the ref attribute is used on a HTML element, the ref callback receives the underlying DOM element as its argument. For example, this code uses the ref callback to store a reference to a DOM node:

+
class CustomTextInput extends React.Component {
+  constructor(props) {
+    super(props);
+    this.focus = this.focus.bind(this);
+  }
+
+  focus() {
+    // Explicitly focus the text input using the raw DOM API
+    this.textInput.focus();
+  }
+
+  render() {
+    // Use the `ref` callback to store a reference to the text input DOM
+    // element in this.textInput
+    return (
+      <div>
+        <input type="text" ref={(input) => this.textInput = input} />
+        <input
+          type="button"
+          value="Focus the text input"
+          onClick={this.focus}
+        />
+      </div>
+    );
+  }
+}
+
+

React will call the ref callback with the DOM element when the component mounts, and call it with null when it unmounts.

+ +

Using the ref callback just to set a property on the class is a common pattern for accessing DOM elements. If you are currently using this.refs.myRefName to access refs, we recommend using this pattern instead.

+ +

When the ref attribute is used on a custom component, the ref callback receives the mounted instance of the component as its argument. For example, if we wanted to wrap the CustomTextInput above to simulate it being clicked immediately after mounting:

+
class AutoFocusTextInput extends React.Component {
+  componentDidMount() {
+    this.textInput.focus();
+  }
+
+  render() {
+    return <CustomTextInput ref={(input) => this.textInput = input} />;
+  }
+}
+
+

You may not use the ref attribute on functional components because they don't have instances. You can, however, use the ref attribute inside the render function of a functional component:

+
function CustomTextInput(props) {
+  // textInput must be declared here so the ref callback can refer to it
+  let textInput;
+
+  function handleClick() {
+    textInput.focus();
+  }
+
+  return (
+    <div>
+      <input type="text" ref={(input) => textInput = input} />
+      <input
+        type="button"
+        value="Focus the text input"
+        onClick={handleClick}
+      />
+    </div>
+  );  
+}
+

Don't Overuse Refs #

+

Your first inclination may be to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy - see the Lifting State Up guide for examples of this.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/rendering-elements.html b/docs/rendering-elements.html new file mode 100644 index 0000000000..1693eef959 --- /dev/null +++ b/docs/rendering-elements.html @@ -0,0 +1,475 @@ + + + + + + + + + Rendering Elements - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Rendering Elements +

+
+ +

Elements are the smallest building blocks of React apps.

+ +

An element describes what you want to see on the screen:

+
const element = <h1>Hello, world</h1>;
+
+

Unlike browser DOM elements, React elements are plain objects, and are cheap to create. React DOM takes care of updating the DOM to match the React elements.

+ +
+

Note:

+ +

One might confuse elements with a more widely known concept of "components". We will introduce components in the next section. Elements are what components are "made of", and we encourage you to read this section before jumping ahead.

+
+

Rendering an Element into the DOM #

+

Let's say there is a <div> somewhere in your HTML file:

+
<div id="root"></div>
+
+

We call this a "root" DOM node because everything inside it will be managed by React DOM.

+ +

Applications built with just React usually have a single root DOM node. If you are integrating React into an existing app, you may have as many isolated root DOM nodes as you like.

+ +

To render a React element into a root DOM node, pass both to ReactDOM.render():

+
const element = <h1>Hello, world</h1>;
+ReactDOM.render(
+  element,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

It displays "Hello World" on the page.

+

Updating the Rendered Element #

+

React elements are immutable. Once you create an element, you can't change its children or attributes. An element is like a single frame in a movie: it represents the UI at a certain point in time.

+ +

With our knowledge so far, the only way to update the UI is to create a new element, and pass it to ReactDOM.render().

+ +

Consider this ticking clock example:

+
function tick() {
+  const element = (
+    <div>
+      <h1>Hello, world!</h1>
+      <h2>It is {new Date().toLocaleTimeString()}.</h2>
+    </div>
+  );
+  ReactDOM.render(
+    element,
+    document.getElementById('root')
+  );
+}
+
+setInterval(tick, 1000);
+
+

Try it on CodePen.

+ +

It calls ReactDOM.render() every second from a setInterval() callback.

+ +
+

Note:

+ +

In practice, most React apps only call ReactDOM.render() once. In the next sections we will learn how such code gets encapsulated into stateful components.

+ +

We recommend that you don't skip topics because they build on each other.

+
+

React Only Updates What's Necessary #

+

React DOM compares the element and its children to the previous one, and only applies the DOM updates necessary to bring the DOM to the desired state.

+ +

You can verify by inspecting the last example with the browser tools:

+ +

DOM inspector showing granular updates

+ +

Even though we create an element describing the whole UI tree on every tick, only the text node whose contents has changed gets updated by React DOM.

+ +

In our experience, thinking about how the UI should look at any given moment rather than how to change it over time eliminates a whole class of bugs.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/reusable-components-it-IT.html b/docs/reusable-components-it-IT.html deleted file mode 100644 index c97fa86364..0000000000 --- a/docs/reusable-components-it-IT.html +++ /dev/null @@ -1,705 +0,0 @@ - - - - - - - Componenti Riutilizzabili | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Componenti Riutilizzabili -

-
- -

Quando disegni interfacce, separa gli elementi comuni di design (bottoni, campi dei moduli, componenti di layout, etc.) in componenti riutilizzabili con interfacce ben definite. In questo modo, la prossima volta che dovrai costruire una nuova UI, puoi scrivere molto meno codice. Ciò significa tempi di sviluppo più brevi, meno bachi, e meno byte trasferiti sulla rete.

-

Validazione delle Proprietà #

-

Mentre la tua applicazione cresce, è utile assicurarsi che i tuoi componenti vengano usati correttamente. Ciò viene fatto permettendoti di specificare i propTypes. React.PropTypes esporta una gamma di validatori che possono essere usati per assicurarsi che i dati che ricevi siano validi. Quando ad una proprietà è assegnato un valore non valido, sarà mostrato un avvertimento nella console JavaScript. Nota che per motivi di prestazioni, propTypes è utilizzato soltanto nella modalità di sviluppo. Di seguito trovi un esempio che documenta i diversi validatori che vengono forniti:

-
React.createClass({
-  propTypes: {
-    // Puoi dichiarare che una proprietà è uno specifico tipo primitivo JS. In
-    // maniera predefinita, questi sono tutti opzionali.
-    optionalArray: React.PropTypes.array,
-    optionalBool: React.PropTypes.bool,
-    optionalFunc: React.PropTypes.func,
-    optionalNumber: React.PropTypes.number,
-    optionalObject: React.PropTypes.object,
-    optionalString: React.PropTypes.string,
-    optionalSymbol: React.PropTypes.symbol,
-
-    // Tutto ciò che può essere mostrato: numeri, stringhe, elementi, o un array
-    // (o frammento) contenente questi tipi.
-    optionalNode: React.PropTypes.node,
-
-    // Un elemento React.
-    optionalElement: React.PropTypes.element,
-
-    // Puoi anche dichiarare che una proprietà è un'istanza di una classe. Questo
-    // validatore usa l'operatore instanceof di JS.
-    optionalMessage: React.PropTypes.instanceOf(Message),
-
-    // Puoi assicurarti che la tua proprietà sia ristretta a valori specifici
-    // trattandoli come una enumerazione.
-    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
-
-    // Un oggetto che può essere di uno tra diversi tipi
-    optionalUnion: React.PropTypes.oneOfType([
-      React.PropTypes.string,
-      React.PropTypes.number,
-      React.PropTypes.instanceOf(Message)
-    ]),
-
-    // Un array di un tipo specificato
-    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
-
-    // Un oggetto con proprietà dai valori di un tipo specificato
-    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
-
-    // Un oggetto che accetta una forma particolare
-    optionalObjectWithShape: React.PropTypes.shape({
-      color: React.PropTypes.string,
-      fontSize: React.PropTypes.number
-    }),
-
-    // Puoi concatenare ciascuna delle precedenti con `isRequired` per assicurarti
-    // che venga mostrato un avvertimento se la proprietà non viene impostata.
-    requiredFunc: React.PropTypes.func.isRequired,
-
-    // Un valore di un tipo qualsiasi
-    requiredAny: React.PropTypes.any.isRequired,
-
-    // Puoi inoltre specificare un validatore personalizzato. Deve restituire un
-    // oggetto di tipo Error se la validazione fallisce. Non lanciare eccezioni
-    // o utilizzare `console.warn`, in quanto non funzionerebbe all'interno di
-    // `oneOfType`.
-    customProp: function(props, propName, componentName) {
-      if (!/matchme/.test(props[propName])) {
-        return new Error('Validazione fallita!');
-      }
-    }
-  },
-  /* ... */
-});
-

Valori Predefiniti delle Proprietà #

-

React ti permette di definire valori predefiniti per le tue props in una maniera molto dichiarativa:

-
var ComponentWithDefaultProps = React.createClass({
-  getDefaultProps: function() {
-    return {
-      value: 'valore predefinito'
-    };
-  }
-  /* ... */
-});
-
-

Il risultato di getDefaultProps() sarà conservato e usato per assicurarsi che this.props.value avrà sempre un valore se non è stato specificato dal componente proprietario. Ciò ti permette di utilizzare in sicurezza le tue proprietà senza dover scrivere codice fragile e ripetitivo per gestirlo da te.

-

Trasferire le Proprietà: Una Scorciatoia #

-

Un tipo comune di componente React è uno che estende un elemento basico HTML in maniera semplice. Spesso vorrai copiare qualsiasi attributo HTML passato al tuo componente all'elemento HTML sottostante per risparmiare del codice. Puoi usare la sintassi spread di JSX per ottenerlo:

-
var CheckLink = React.createClass({
-  render: function() {
-    // Questo prende ciascuna proprietà passata a CheckLink e la copia su <a>
-    return <a {...this.props}>{'√ '}{this.props.children}</a>;
-  }
-});
-
-ReactDOM.render(
-  <CheckLink href="/checked.html">
-    Clicca qui!
-  </CheckLink>,
-  document.getElementById('example')
-);
-

Figlio Singolo #

-

Con React.PropTypes.element puoi specificare che solo un figlio unico possa essere passato come figli ad un componente.

-
var MyComponent = React.createClass({
-  propTypes: {
-    children: React.PropTypes.element.isRequired
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.props.children} // Questo deve essere esattamente un elemento oppure lancerà un'eccezione.
-      </div>
-    );
-  }
-
-});
-

Mixin #

-

I componenti sono la maniera migliore di riutilizzare il codice in React, ma a volte componenti molto diversi possono condividere funzionalità comune. Questi sono a volte chiamate responsabilità trasversali. React fornisce i mixin per risolvere questo problema.

- -

Un caso d'uso comune è un componente che desidera aggiornarsi ad intervalli di tempo. È facile usare setInterval(), ma è anche importante cancellare la chiamata ripetuta quando non è più necessaria per liberare memoria. React fornisce dei metodi del ciclo di vita che ti permettono di sapere quando un componente sta per essere creato o distrutto. Creiamo un semplice mixin che usa questi metodi per fornire una facile funzione setInterval() che sarà automaticamente rimossa quando il tuo componente viene distrutto.

-
var SetIntervalMixin = {
-  componentWillMount: function() {
-    this.intervals = [];
-  },
-  setInterval: function() {
-    this.intervals.push(setInterval.apply(null, arguments));
-  },
-  componentWillUnmount: function() {
-    this.intervals.forEach(clearInterval);
-  }
-};
-
-var TickTock = React.createClass({
-  mixins: [SetIntervalMixin], // Usa il mixin
-  getInitialState: function() {
-    return {seconds: 0};
-  },
-  componentDidMount: function() {
-    this.setInterval(this.tick, 1000); // Chiama un metodo del mixin
-  },
-  tick: function() {
-    this.setState({seconds: this.state.seconds + 1});
-  },
-  render: function() {
-    return (
-      <p>
-        React has been running for {this.state.seconds} seconds.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <TickTock />,
-  document.getElementById('example')
-);
-
-

Una caratteristica interessante dei mixin è che, se un componente usa molteplici mixin e diversi mixin definiscono lo stesso metodo del ciclo di vita (cioè diversi mixin desiderano effettuare una pulizia quando il componente viene distrutto), viene garantito che tutti i metodi del ciclo di vita verranno chiamati. I metodi definiti nei mixin vengono eseguiti nell'ordine in cui i mixin sono elencati, seguiti da una chiamata al metodo definito nel componente.

-

Classi ES6 #

-

Puoi anche definire le tue classi React come pure classi JavaScript. Per esempio, usando la sintassi delle classi ES6:

-
class HelloMessage extends React.Component {
-  render() {
-    return <div>Ciao {this.props.name}</div>;
-  }
-}
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

L'API è simile a React.createClass con l'eccezione del metodo getInitialState. Anziché fornire un metodo getInitialState a parte, imposti la tua proprietà state nel costruttore.

- -

Un'altra differenza è che propTypes e defaultProps sono definite come proprietà del costruttore anziché nel corpo della classe.

-
export class Counter extends React.Component {
-  constructor(props) {
-    super(props);
-    this.state = {count: props.initialCount};
-  }
-  tick() {
-    this.setState({count: this.state.count + 1});
-  }
-  render() {
-    return (
-      <div onClick={this.tick.bind(this)}>
-        Click: {this.state.count}
-      </div>
-    );
-  }
-}
-Counter.propTypes = { initialCount: React.PropTypes.number };
-Counter.defaultProps = { initialCount: 0 };
-

Niente Binding Automatico #

-

I metodi seguono la stessa semantica delle classi ES6 regolari, ciò significa che non effettuano il binding automatico di this all'istanza. Dovrai pertanto usare esplicitamente .bind(this) oppure le funzioni freccia =>.

-

Niente Mixin #

-

Sfortunatamente, ES6 è stato lanciato senza alcun supporto per i mixin. Di conseguenza non vi è alcun supporto per i mixin quando usi React con le classi ES6. Stiamo lavorando per rendere più semplice il supporto dei relativi casi d'uso senza ricorrere ai mixin.

-

Funzioni Prive di Stato #

-

Puoi anche definire le tue classi React come semplici funzioni JavaScript. Ad esempio usando la sintassi della funzione priva di stato:

-
function HelloMessage(props) {
-  return <div>Ciao {props.name}</div>;
-}
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

Oppure usando la nuova sintassi freccia di ES6:

-
const HelloMessage = (props) => <div>Ciao {props.name}</div>;
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

Questa API semplificata dei componenti è intesa per i componenti che sono pure funzioni dele proprietà. Questi componenti non devono trattenere stato interno, non hanno istanze di supporto, e non posseggono metodi di ciclo di vita. Sono pure trasformate funzionali del loro input, con zero codice boilerplate.

- -
-

NOTA:

- -

Poiché le funzioni prive di stato non hanno un'istanza di supporto, non puoi assegnare un ref a un componente creato con una funzione priva di stato. Normalmente questo non è un problema, poiché le funzioni prive di stato non forniscono un'API imperativa. Senza un'API imperativa, non puoi comunque fare molto con un'istanza. Tuttavia, se un utente desidera trovare il nodo DOM di un componente creato con una funzione priva di stato, occorre avvolgere il componente in un altro componente dotato di stato (ad es. un componente classe ES6) e assegnare il ref al componente dotato di stato.

-
- -

In un mondo ideale, la maggior parte dei tuoi componenti sarebbero funzioni prive di stato poiché questi componenti privi di stato seguono un percorso più rapido all'interno del core di React. Questo è un pattern raccomandato, quando possibile.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/reusable-components-ja-JP.html b/docs/reusable-components-ja-JP.html deleted file mode 100644 index e9becbb5c7..0000000000 --- a/docs/reusable-components-ja-JP.html +++ /dev/null @@ -1,683 +0,0 @@ - - - - - - - 再利用可能なコンポーネント | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 再利用可能なコンポーネント -

-
- -

インターフェースをデザインするとき、明確に定義されたインターフェースでは共通のデザイン要素(ボタン、フォームフィールド、レイアウトコンポーネントなど)を再利用可能なコンポーネントにブレークダウンします。そのような方法をとることで、次にUIを作成する必要があるときに、書くコードが少なくて済みます。これは、開発速度を上げ、バグを減らし、導線を減らすことを意味します。

-

Propのバリデーション #

-

アプリが大きくなっていくにつれて、コンポーネントが正しく使われていることを保証することが役に立つようになります。propTypes を指定することでそういったことができるようになります。React.PropTypes はあなたが受け取ったデータが正しいことを認識するのに使われるバリデータを出力します。不正な値がpropに渡されたときは、警告がJavaScriptコンソールに表示されます。パフォーマンスの点で、 propTypes は開発モードでのみチェックされることに注意してください。異なるバリデータが提供された際の例を表すドキュメントは以下の通りです。

-
React.createClass({
-  propTypes: {
-    // propがJSのプリミティブ型であると宣言できます。
-    // デフォルトで、以下は全てオプションです。
-    optionalArray: React.PropTypes.array,
-    optionalBool: React.PropTypes.bool,
-    optionalFunc: React.PropTypes.func,
-    optionalNumber: React.PropTypes.number,
-    optionalObject: React.PropTypes.object,
-    optionalString: React.PropTypes.string,
-    optionalSymbol: React.PropTypes.symbol,
-
-    // 何でもレンダリングできます。number、string、要素やそれらを含む配列など。
-    optionalNode: React.PropTypes.node,
-
-    // Reactの要素。
-    optionalElement: React.PropTypes.element,
-
-    // propがクラスのインスタンスであるとの宣言もできます。
-    // JSのinstanceofオペレータを使用しています。
-    optionalMessage: React.PropTypes.instanceOf(Message),
-
-    // 以下をenumとして扱うことで、propがある値であると保証できます。
-    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
-
-    // たくさんの型のうちのひとつになりうるオブジェクト
-    optionalUnion: React.PropTypes.oneOfType([
-      React.PropTypes.string,
-      React.PropTypes.number,
-      React.PropTypes.instanceOf(Message)
-    ]),
-
-    // ある型の配列
-    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
-
-    // プロパティの値がある型のものであるオブジェクト
-    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
-
-    // 特定の形をとるオブジェクト
-    optionalObjectWithShape: React.PropTypes.shape({
-      color: React.PropTypes.string,
-      fontSize: React.PropTypes.number
-    }),
-
-    // `isRequired` は上記のどの値にも繋げることができますが、
-    // propが提供されなかったときには警告が出ることに注意してください。
-    requiredFunc: React.PropTypes.func.isRequired,
-
-    // どのようなデータ型の値でも大丈夫です
-    requiredAny: React.PropTypes.any.isRequired,
-
-    // バリデータをカスタマイズすることもできます。
-    // 以下はバリデーションが落ちた時にはエラーを返します。
-    // `oneOfType` の中で動かなくなるので、 `console.warn` や throw はしないでください。
-    customProp: function(props, propName, componentName) {
-      if (!/matchme/.test(props[propName])) {
-        return new Error('Validation failed!');
-      }
-    }
-  },
-  /* ... */
-});
-

デフォルトのPropの値 #

-

Reactは以下のように、とても宣言的な方法で props のデフォルト値を定義できます。

-
var ComponentWithDefaultProps = React.createClass({
-  getDefaultProps: function() {
-    return {
-      value: 'default value'
-    };
-  }
-  /* ... */
-});
-
-

getDefaultProps() の結果は this.props.value が親コンポーネントで制限されなかった場合に値を保証するためにキャッシュされて使われます。これによって、自分自身でハンドルするための壊れやすいコードを何度も書くことなくpropsをただ安全に使うことができます。

-

Propsの移動: ショートカット #

-

Reactのコンポーネントに共通しているのは、単純な方法で基本的なHTML要素を拡張していることです。よく、 -コンポーネントに渡されるHTML属性を、型付けを守るために、基本的なHTML要素にコピーしたいと考える人もいます。このようなことを行うために、JSXの 拡張された シンタックスを使うことができます。

-
var CheckLink = React.createClass({
-  render: function() {
-    // 以下はCheckLinkに渡されたどんなpropsをとることができ、<a>タグにコピーすることもできます。
-    return <a {...this.props}>{'√ '}{this.props.children}</a>;
-  }
-});
-
-ReactDOM.render(
-  <CheckLink href="/checked.html">
-    Click here!
-  </CheckLink>,
-  document.getElementById('example')
-);
-

単一の子要素 #

-

React.PropTypes.element を使って、childrenとしてコンポーネントにただ一つの子要素が渡されるよう制限できます。

-
var MyComponent = React.createClass({
-  propTypes: {
-    children: React.PropTypes.element.isRequired
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.props.children} // これは1つの要素でなくてはなりません。さもなければエラーがthrowされます。
-      </div>
-    );
-  }
-
-});
-

ミックスイン #

-

コンポーネントはReactでコードを再利用する最良の方法ですが、全く異なったコンポーネントが共通の機能性を共有することもあります。それらは横断的関心事と呼ばれることもあります。Reactはこの問題を解決するために、 mixins を提供しています。

- -

共通のユースケースとしては、時間の間隔によって、コンポーネントにそれ自身をアップデートさせたい場合があります。 setInterval() を使うのは簡単ですが、メモリをセーブするためにもう必要でなくなった場合にはインターバルをキャンセルすることが重要です。Reactはライフサイクルメソッドを提供しており、コンポーネントが作成されようとしたり削除されようとした時にそれを検知することができます。コンポーネントが削除されたときに自動的にクリーンアップしてくれる、簡単な setInterval() 関数を提供する以下のようなメソッドを使って単純なミックスインを作成してみましょう。

-
var SetIntervalMixin = {
-  componentWillMount: function() {
-    this.intervals = [];
-  },
-  setInterval: function() {
-    this.intervals.push(setInterval.apply(null, arguments));
-  },
-  componentWillUnmount: function() {
-    this.intervals.forEach(clearInterval);
-  }
-};
-
-var TickTock = React.createClass({
-  mixins: [SetIntervalMixin], // ミックスインを使う
-  getInitialState: function() {
-    return {seconds: 0};
-  },
-  componentDidMount: function() {
-    this.setInterval(this.tick, 1000); // ミックスインのメソッドを呼ぶ
-  },
-  tick: function() {
-    this.setState({seconds: this.state.seconds + 1});
-  },
-  render: function() {
-    return (
-      <p>
-        React has been running for {this.state.seconds} seconds.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <TickTock />,
-  document.getElementById('example')
-);
-
-

ミックスインの素晴らしい特徴はコンポーネントが複数のミックスインを使っていて、いくつかのミックスインが同じライフサイクルメソッドを定義している場合(すなわち、コンポーネントが削除された際に幾つかのミックスインがクリーンアップを行いたい場合)に、すべてのライフサイクルメソッドが呼ばれることを保証することです。ミックスインで定義されたメソッドは、ミックスインが並んでいる順番に走り、コンポーネントのメソッド呼び出しで呼ばれます。

-

ES6のクラス #

-

ReactのクラスをただのJavaScriptのクラスとして定義することもできます。例えば、ES6 のクラスシンタックスを使うと、以下のようになります。

-
class HelloMessage extends React.Component {
-  render() {
-    return <div>Hello {this.props.name}</div>;
-  }
-}
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

APIは getInitialState という例外を除き、 React.createClass と同じです。APIが異なっている getInitialState メソッドを提供する代わりに、コンストラクタの中に state プロパティをセットします。

- -

他の違いは、 propTypesdefaultProps はクラスのボディに定義される代わりにコンストラクタにプロパティとして定義されます。

-
export class Counter extends React.Component {
-  constructor(props) {
-    super(props);
-    this.state = {count: props.initialCount};
-  }
-  tick() {
-    this.setState({count: this.state.count + 1});
-  }
-  render() {
-    return (
-      <div onClick={this.tick.bind(this)}>
-        Clicks: {this.state.count}
-      </div>
-    );
-  }
-}
-Counter.propTypes = { initialCount: React.PropTypes.number };
-Counter.defaultProps = { initialCount: 0 };
-

オートバインディングしません #

-

メソッドは標準のES6のクラスと同じ仕様です。それは、 this をインスタンスに自動的にバインドしないことを意味します。明確に .bind(this) を使うか アロー関数 => を使ってください。

-

ミックスインはありません #

-

不幸なことに、ES6はミックスインのサポートを行いません。それゆえ、ReactをES6のクラスと一緒に使う際にはミックスインのサポートはありません。代わりに、ミックスインに頼ることなくそれらのユースケースをサポートするのが簡単になるよう努力しています。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/reusable-components-ko-KR.html b/docs/reusable-components-ko-KR.html deleted file mode 100644 index 39be466f19..0000000000 --- a/docs/reusable-components-ko-KR.html +++ /dev/null @@ -1,703 +0,0 @@ - - - - - - - 재사용가능한 컴포넌트 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 재사용가능한 컴포넌트 -

-
- -

인터페이스를 설계할 때, 공통적으로 사용되는 디자인 요소들(버튼, 폼 필드, 레이아웃 컴포넌트 등.)을 잘 정의된 인터페이스의 재사용 가능한 컴포넌트로 분해합니다. 이런 방법으로 다음에 UI를 구축할 때에는 훨씬 적은 코드로 만들 수 있습니다. 이 말은 더 빠른 개발 시간, 더 적은 버그, 더 적은 용량으로 할 수 있다는 뜻이죠.

-

Prop 검증 #

-

앱의 규모가 커지면 컴포넌트들이 바르게 사용되었는지 확인하는게 도움이 됩니다. 확인은 propTypes를 명시해서 할 수 있습니다. React.PropTypes는 받은 데이터가 적절한지(valid) 확인하는데 사용할 수 있는 다양한 검증자(validator)를 제공합니다. prop에 부적절한 값을 명시한다면 JavaScript 콘솔에 경고가 보일 것입니다. 성능상의 문제로 propTypes는 개발 모드에서만 검사됩니다. 다음은 제공되는 검증자를 설명하는 예제입니다.

-
React.createClass({
-  propTypes: {
-    // 특정 JavaScript 프리미티브 타입에 대한 prop을 명시할 수 있습니다.
-    // 기본적으로 이것들은 모두 선택적입니다.
-    optionalArray: React.PropTypes.array,
-    optionalBool: React.PropTypes.bool,
-    optionalFunc: React.PropTypes.func,
-    optionalNumber: React.PropTypes.number,
-    optionalObject: React.PropTypes.object,
-    optionalString: React.PropTypes.string,
-    optionalSymbol: React.PropTypes.symbol,
-
-    // 렌더링될 수 있는 모든 것: 숫자, 문자열, 요소
-    // 이것들을 포함하는 배열(이나 프래그먼트)
-    optionalNode: React.PropTypes.node,
-
-    // React 엘리먼트
-    optionalElement: React.PropTypes.element,
-
-    // 클래스의 인스턴스 또한 prop으로 명시할 수 있습니다. JavaScript의 instanceof
-    // 연산자를 사용합니다.
-    optionalMessage: React.PropTypes.instanceOf(Message),
-
-    // 열거형처럼 특정 값들로만 prop을 제한해서 사용할 수 있습니다.
-    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
-
-    // 많은 타입들 중 하나로 사용할 수 있는 객체가 될 수도 있습니다.
-    optionalUnion: React.PropTypes.oneOfType([
-      React.PropTypes.string,
-      React.PropTypes.number,
-      React.PropTypes.instanceOf(Message)
-    ]),
-
-    // 특정 타입의 배열
-    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
-
-    // 특정 타입의 속성값을 갖는 객체
-    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
-
-    // 특정한 형태(shape)의 객체
-    optionalObjectWithShape: React.PropTypes.shape({
-      color: React.PropTypes.string,
-      fontSize: React.PropTypes.number
-    }),
-
-    // 위에 언급된 것들을 `isRequired`로 연결해서 prop이 제공되지 않을 때 경고를
-    // 띄우도록 할 수도 있습니다.
-    requiredFunc: React.PropTypes.func.isRequired,
-
-    // 어떤 데이터 타입도 가능
-    requiredAny: React.PropTypes.any.isRequired,
-
-    // 물론 사용자 정의 검증자도 지정할 수 있습니다. 이는 검증이 실패했을 때
-    // Error 객체를 리턴해야합니다. `console.warn`을 이나 throw를 하면 안됩니다.
-    // 그렇게하면 `oneOfType` 안에서 작동하지 않습니다.
-    customProp: function(props, propName, componentName) {
-      if (!/matchme/.test(props[propName])) {
-        return new Error('Validation failed!');
-      }
-    }
-  },
-  /* ... */
-});
-

기본 Prop 값 #

-

React는 매우 선언적(declarative)인 방법으로 props의 기본값을 정의할 수 있게 해줍니다.

-
var ComponentWithDefaultProps = React.createClass({
-  getDefaultProps: function() {
-    return {
-      value: 'default value'
-    };
-  }
-  /* ... */
-});
-
-

getDefaultProps()의 결과값은 캐시가 되며, 부모 컴포넌트에서 명시되지 않았을 때 this.props.value가 값을 가질 수 있도록 해주는데 사용됩니다.getDefaultProps()를 사용하면 반복적이고 깨지기 쉬운 코드를 짤 필요없이 그냥 안전하게 prop을 사용할 수 있습니다.

-

Prop 전달하기: 단축 #

-

React 컴포넌트의 흔히 그냥 기본 HTML 엘리먼트를 확장해서 씁니다. 타이핑을 아끼기 위해 기저의 HTML 엘리먼트에 HTML 속성들을 단순히 복사하는 컴포넌트가 필요할 수도 있습니다. JSX의 spread 문법을 사용하면 이렇게 할 수 있습니다.

-
var CheckLink = React.createClass({
-  render: function() {
-    // 모든 prop을 받아서 CheckLink에 넘기고 <a>에 복사합니다.
-    return <a {...this.props}>{'√ '}{this.props.children}</a>;
-  }
-});
-
-ReactDOM.render(
-  <CheckLink href="/checked.html">
-    Click here!
-  </CheckLink>,
-  document.getElementById('example')
-);
-

단일 자식 #

-

React.PropTypes.element을 통해 컴포넌트에 한 자식만 보내도록 명시할 수 있습니다.

-
var MyComponent = React.createClass({
-  propTypes: {
-    children: React.PropTypes.element.isRequired
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.props.children} // 정확히 한 엘리먼트여야만 하며, 아니면 에러가 발생합니다.
-      </div>
-    );
-  }
-
-});
-

믹스인 #

-

컴포넌트는 React에서 코드를 재사용할 수 있는 최고의 방법이지만, 가끔 아주 다른 컴포넌트에서 공통 기능이 필요한 때도 있습니다. 이런 상황을 공통된 관심사(cross-cutting concerns)라 부르며, React에서는 mixins으로 이 문제를 해결합니다.

- -

예를 들어, 컴포넌트가 주기적으로 업데이트되길 원할 경우가 있습니다. setInterval()을 사용하면 쉽지만, 필요 없어지면 메모리를 아끼기 위해 주기를 꼭 취소해야 합니다. React는 컴포넌트가 막 생성거나 없어질 때를 생명주기 메소드를 통해 알려줍니다. 이런 메소드들을 사용해서 컴포넌트가 사라질 때 자동으로 정리해주는 setInterval()를 제공해주는 간단한 믹스인을 만들어보겠습니다.

-
var SetIntervalMixin = {
-  componentWillMount: function() {
-    this.intervals = [];
-  },
-  setInterval: function() {
-    this.intervals.push(setInterval.apply(null, arguments));
-  },
-  componentWillUnmount: function() {
-    this.intervals.forEach(clearInterval);
-  }
-};
-
-var TickTock = React.createClass({
-  mixins: [SetIntervalMixin], // 믹스인 사용
-  getInitialState: function() {
-    return {seconds: 0};
-  },
-  componentDidMount: function() {
-    this.setInterval(this.tick, 1000); // 믹스인에 있는 메소드를 호출
-  },
-  tick: function() {
-    this.setState({seconds: this.state.seconds + 1});
-  },
-  render: function() {
-    return (
-      <p>
-        React has been running for {this.state.seconds} seconds.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <TickTock />,
-  document.getElementById('example')
-);
-
-

믹스인의 괜찮은 점은 컴포넌트가 여러 믹스인을 사용하고 여러 믹스인에서 같은 생명주기 메소드를 사용할 때(예를 들어, 여러 믹스인에서 컴포넌트가 사라질 때 뭔가 정리하려 한다면) 모든 생명주기 메소드들의 실행은 보장됩니다. 믹스인에 정의된 메소드은 컴포넌트의 메소드가 호출됨에 따라 믹스인이 나열된 순서대로 실행됩니다.

-

ES6 클래스 #

-

React 클래스를 일반적인 JavaScript 클래스로 선언할 수도 있습니다. 다음의 예제는 ES6 클래스 문법을 사용합니다:

-
class HelloMessage extends React.Component {
-  render() {
-    return <div>Hello {this.props.name}</div>;
-  }
-}
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

API는 getInitialState를 제외하고 React.createClass와 유사합니다. 별도의 getInitialState 메소드 대신에, 필요한 state 프로퍼티를 생성자에서 설정할 수 있습니다.

- -

또다른 차이점은 propTypesdefaultProps가 클래스의 내부가 아니라 생성자의 프로퍼티로 정의되어 있다는 것입니다.

-
export class Counter extends React.Component {
-  constructor(props) {
-    super(props);
-    this.state = {count: props.initialCount};
-  }
-  tick() {
-    this.setState({count: this.state.count + 1});
-  }
-  render() {
-    return (
-      <div onClick={this.tick.bind(this)}>
-        Clicks: {this.state.count}
-      </div>
-    );
-  }
-}
-Counter.propTypes = { initialCount: React.PropTypes.number };
-Counter.defaultProps = { initialCount: 0 };
-

자동 바인딩 안됨 #

-

메소드는 일반 ES6 클래스와 동일한 시멘틱을 따릅니다. this를 인스턴스에 자동으로 바인딩하지 않는다는 이야기입니다. 명시적으로 .bind(this)화살표 함수(arrow function) =>를 사용하세요.

-

믹스인 안됨 #

-

불행하게도 ES6는 믹스인에 대한 지원이 없이 출시되었기 때문에, React에서 ES6 클래스를 사용한다면 믹스인을 사용할 방법이 없습니다. 대신, 우리는 믹스인에 의존하지 않고도 동작하도록 만들기 위해 열심히 노력하고 있습니다.

-

상태를 가지지 않는 함수 #

-

React 클래스를 일반 JavaScript 함수로 작성할 수도 있습니다. 상태를 가지지 않는 함수 문법을 사용하는 예제입니다.

-
function HelloMessage(props) {
-  return <div>Hello {props.name}</div>;
-}
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

아니면 ES6의 화살표 문법을 사용할 수 있습니다.

-
const HelloMessage = (props) => <div>Hello {props.name}</div>;
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

이 단순화된 컴포넌트 API는 prop의 순수 함수인 컴포넌트를 나타냅니다. 이 컴포넌트는 내부 상태가 없어야 하고, 내부 인스턴스가 없어야 하고, 컴포넌트 생명주기 메소드가 없어야 합니다. 아무런 준비 과정없이 입력에 대한 순수한 기능적 변환이어야 합니다.

- -
-

주의:

- -

상태를 가지지 않는 함수는 내부 인스턴스가 없기 때문에, ref를 상태를 가지지않는 함수에 넣을 수 없습니다. 상태를 가지지 않는 함수는 명령형(imperative) API를 제공하지 않기 때문에 일반적으로 이것은 문제가 되지 않습니다. 명령형 API없이 인스턴스에 할 수 있는 것이 많지 않기도 하죠. 하지만 상태를 가지지 않는 컴포넌트의 DOM 노드를 검색하길 원한다면, 반드시 상태 기반 컴포넌트(예. ES6 클래스 컴포넌트)로 컴포넌트를 감싸고 상태 기반 래퍼 컴포넌트에 ref를 붙여야 합니다.

-
- -

이상적으로는, 대부분의 컴포넌트는 상태를 가지지 않는 함수여야 합니다. 왜냐 하면 이런 상태를 가지지 않는 컴포넌트는 React 코어 안에서 더 빠른 코드 경로를 거치기 때문입니다. 이는 가능한 한 추천하는 패턴입니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/reusable-components-zh-CN.html b/docs/reusable-components-zh-CN.html deleted file mode 100644 index e4ffdbb45a..0000000000 --- a/docs/reusable-components-zh-CN.html +++ /dev/null @@ -1,723 +0,0 @@ - - - - - - - 可复用组件 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 可复用组件 -

-
- -

设计接口的时候,把通用的设计元素(按钮,表单框,布局组件等)拆成接口良好定义的可复用的组件。这样,下次开发相同界面程序时就可以写更少的代码,也意义着更高的开发效率,更少的 Bug 和更少的程序体积。

-

Prop 验证 #

-

随着应用不断变大,保证组件被正确使用变得非常有用。为此我们引入 propTypesReact.PropTypes 提供很多验证器 (validator) 来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。注意为了性能考虑,只在开发环境验证 propTypes。下面用例子来说明不同验证器的区别:

-
React.createClass({
-  propTypes: {
-    // 可以声明 prop 为指定的 JS 基本类型。默认
-    // 情况下,这些 prop 都是可传可不传的。
-    optionalArray: React.PropTypes.array,
-    optionalBool: React.PropTypes.bool,
-    optionalFunc: React.PropTypes.func,
-    optionalNumber: React.PropTypes.number,
-    optionalObject: React.PropTypes.object,
-    optionalString: React.PropTypes.string,
-    optionalSymbol: React.PropTypes.symbol,
-
-    // 所有可以被渲染的对象:数字,
-    // 字符串,DOM 元素或包含这些类型的数组(or fragment) 。
-    optionalNode: React.PropTypes.node,
-
-    // React 元素
-    optionalElement: React.PropTypes.element,
-
-    // 你同样可以断言一个 prop 是一个类的实例。
-    // 用 JS 的 instanceof 操作符声明 prop 为类的实例。
-    optionalMessage: React.PropTypes.instanceOf(Message),
-
-    // 你可以用 enum 的方式
-    // 确保你的 prop 被限定为指定值。
-    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
-
-    // 指定的多个对象类型中的一个
-    optionalUnion: React.PropTypes.oneOfType([
-      React.PropTypes.string,
-      React.PropTypes.number,
-      React.PropTypes.instanceOf(Message)
-    ]),
-
-    // 指定类型组成的数组
-    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
-
-    // 指定类型的属性构成的对象
-    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
-
-    // 特定形状参数的对象
-    optionalObjectWithShape: React.PropTypes.shape({
-      color: React.PropTypes.string,
-      fontSize: React.PropTypes.number
-    }),
-
-    // 你可以在任意东西后面加上 `isRequired`
-    // 来确保 如果 prop 没有提供 就会显示一个警告。
-    requiredFunc: React.PropTypes.func.isRequired,
-
-    // 不可空的任意类型
-    requiredAny: React.PropTypes.any.isRequired,
-
-    // 你可以自定义一个验证器。如果验证失败需要返回一个 Error 对象。
-    // 不要直接使用 `console.warn` 或抛异常,
-    // 因为这在 `oneOfType` 里不起作用。
-    customProp: function(props, propName, componentName) {
-      if (!/matchme/.test(props[propName])) {
-        return new Error('Validation failed!');
-      }
-    }
-  },
-  /* ... */
-});
-

Single Child #

-

React.PropTypes.element 你可以指定仅有一个子级能被传送给组件

-
var MyComponent = React.createClass({
-  propTypes: {
-    children: React.PropTypes.element.isRequired
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.props.children} // 这里必须是一个元素否则就会警告
-      </div>
-    );
-  }
-
-});
-

默认 Prop 值 #

-

React 支持以声明式的方式来定义 props 的默认值。

-
var ComponentWithDefaultProps = React.createClass({
-  getDefaultProps: function() {
-    return {
-      value: 'default value'
-    };
-  }
-  /* ... */
-});
-
-

当父级没有传入 props 时,getDefaultProps() 可以保证 this.props.value 有默认值,注意 getDefaultProps 的结果会被 缓存。得益于此,你可以直接使用 props,而不必写手动编写一些重复或无意义的代码。

-

传递 Props:捷径 #

-

有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想复制任何传进你的组件的HTML属性到底层的HTML元素上。为了减少输入,你可以用 JSX spread 语法来完成:

-
var CheckLink = React.createClass({
-  render: function() {
-    // 这样会把 CheckList 所有的 props 复制到 <a>
-    return <a {...this.props}>{'√ '}{this.props.children}</a>;
-  }
-});
-
-ReactDOM.render(
-  <CheckLink href="/checked.html">
-    Click here!
-  </CheckLink>,
-  document.getElementById('example')
-);
-

Mixins #

-

组件是 React 里复用代码的最佳方式,但是有时一些不同的组件间也需要共用一些功能。有时会被称为 跨切面关注点。React 使用 mixins 来解决这类问题。

- -

一个通用的场景是:一个组件需要定期更新。用 setInterval() 做很容易,但当不需要它的时候取消定时器来节省内存是非常重要的。React 提供 生命周期方法 来告知你组件创建或销毁的时间。下面来做一个简单的 mixin,使用 setInterval() 并保证在组件销毁时清理定时器。

-
var SetIntervalMixin = {
-  componentWillMount: function() {
-    this.intervals = [];
-  },
-  setInterval: function() {
-    this.intervals.push(setInterval.apply(null, arguments));
-  },
-  componentWillUnmount: function() {
-    this.intervals.forEach(clearInterval);
-  }
-};
-
-var TickTock = React.createClass({
-  mixins: [SetIntervalMixin], // 引用 mixin
-  getInitialState: function() {
-    return {seconds: 0};
-  },
-  componentDidMount: function() {
-    this.setInterval(this.tick, 1000); // 调用 mixin 的方法
-  },
-  tick: function() {
-    this.setState({seconds: this.state.seconds + 1});
-  },
-  render: function() {
-    return (
-      <p>
-        React has been running for {this.state.seconds} seconds.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <TickTock />,
-  document.getElementById('example')
-);
-
-

关于 mixin 值得一提的优点是,如果一个组件使用了多个 mixin,并用有多个 mixin 定义了同样的生命周期方法(如:多个 mixin 都需要在组件销毁时做资源清理操作),所有这些生命周期方法都保证会被执行到。方法执行顺序是:首先按 mixin 引入顺序执行 mixin 里方法,最后执行组件内定义的方法。

-

ES6 Classes #

-

你也可以以一个简单的 JavaScript 类来定义你的React classes。使用ES6 class的例子:

-
class HelloMessage extends React.Component {
-  render() {
-    return <div>Hello {this.props.name}</div>;
-  }
-}
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

API近似于 React.createClass 除了 getInitialState。 你应该在构造函数里设置你的state,而不是提供一个单独的 getInitialState 方法。就像 getInitialState 的返回值,你赋给 this.state 的值会被作为组件的初始 state。

- -

另一个不同是 propTypesdefaultProps 是在构造函数里被定义为属性,而不是在 class body 里。

-
export class Counter extends React.Component {
-  constructor(props) {
-    super(props);
-    this.state = {count: props.initialCount};
-  }
-  tick() {
-    this.setState({count: this.state.count + 1});
-  }
-  render() {
-    return (
-      <div onClick={this.tick.bind(this)}>
-        Clicks: {this.state.count}
-      </div>
-    );
-  }
-}
-Counter.propTypes = { initialCount: React.PropTypes.number };
-Counter.defaultProps = { initialCount: 0 };
-

无自动绑定 #

-

方法遵循正式的ES6 class的语义,意味着它们不会自动绑定this到实例上。你必须显示的使用.bind(this) or 箭头函数 =>

-
// 你可以使用 bind() 来绑定 `this`
-<div onClick={this.tick.bind(this)}>
-
-// 或者你可以使用箭头函数
-<div onClick={() => this.tick()}>
-
-

我们建议你在构造函数中绑定事件处理器,这样对于所有实例它们只需绑定一次:

-
constructor(props) {
-  super(props);
-  this.state = {count: props.initialCount};
-  this.tick = this.tick.bind(this);
-}
-
-

现在你可以直接使用 this.tick 因为它已经在构造函数里绑定过一次了。

-
// 它已经在构造函数里绑定过了
-<div onClick={this.tick}>
-
-

这对应用的性能有帮助,特别是当你用 浅层比较 实现 shouldComponentUpdate() 时。

-

没有 Mixins #

-

不幸的是ES6的发布没有任何mixin的支持。因此,当你在ES6 classes下使用React时不支持mixins。作为替代,我们正在努力使它更容易不依靠mixins支持这些用例。

-

无状态函数 #

-

你也可以用 JavaScript 函数来定义你的 React 类。例如使用无状态函数语法:

-
function HelloMessage(props) {
-  return <div>Hello {props.name}</div>;
-}
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

或者使用新的ES6箭头函数:

-
const HelloMessage = (props) => <div>Hello {props.name}</div>;
-ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

这个简化的组件API旨在用于那些纯函数态的组件 。这些组件必须没有保持任何内部状态,没有备份实例,也没有组件生命周期方法。他们纯粹的函数式的转化他们的输入,没有引用。 -然而,你仍然可以以设置函数 properties 的方式来指定 .propTypes.defaultProps,就像你在ES6类里设置他们那样。

- -
-

注意:

- -

因为无状态函数没有备份实例,你不能附加一个引用到一个无状态函数组件。 通常这不是问题,因为无状态函数不提供一个命令式的API。没有命令式的API,你就没有任何需要实例来做的事。然而,如果用户想查找无状态函数组件的DOM节点,他们必须把这个组件包装在一个有状态组件里(比如,ES6 类组件) 并且连接一个引用到有状态的包装组件。

-
- -

在理想世界里,你的大多数组件都应该是无状态函数,因为将来我们可能会用避免不必要的检查和内存分配的方式来对这些组件进行优化。 如果可能,这是推荐的模式。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/reusable-components.html b/docs/reusable-components.html deleted file mode 100644 index 206d53e280..0000000000 --- a/docs/reusable-components.html +++ /dev/null @@ -1,882 +0,0 @@ - - - - - - - Reusable Components | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Reusable Components -

-
- -

When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc.) into reusable components with well-defined interfaces. That way, the next time you need to build some UI, you can write much less code. This means faster development time, fewer bugs, and fewer bytes down the wire.

-

Prop Validation #

-

As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify propTypes. React.PropTypes exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons propTypes is only checked in development mode.

- -

You can assign a special property to a component to declare its propTypes:

-
class Greeting extends React.Component {
-  render() {
-    return (
-      <h1>Hello, {this.props.name}</h1>
-    );
-  }
-}
-
-Greeting.propTypes = {
-  name: React.PropTypes.string
-};
-
-

Here is an example documenting the different validators provided:

-
MyComponent.propTypes = {
-  // You can declare that a prop is a specific JS primitive. By default, these
-  // are all optional.
-  optionalArray: React.PropTypes.array,
-  optionalBool: React.PropTypes.bool,
-  optionalFunc: React.PropTypes.func,
-  optionalNumber: React.PropTypes.number,
-  optionalObject: React.PropTypes.object,
-  optionalString: React.PropTypes.string,
-  optionalSymbol: React.PropTypes.symbol,
-
-  // Anything that can be rendered: numbers, strings, elements or an array
-  // (or fragment) containing these types.
-  optionalNode: React.PropTypes.node,
-
-  // A React element.
-  optionalElement: React.PropTypes.element,
-
-  // You can also declare that a prop is an instance of a class. This uses
-  // JS's instanceof operator.
-  optionalMessage: React.PropTypes.instanceOf(Message),
-
-  // You can ensure that your prop is limited to specific values by treating
-  // it as an enum.
-  optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
-
-  // An object that could be one of many types
-  optionalUnion: React.PropTypes.oneOfType([
-    React.PropTypes.string,
-    React.PropTypes.number,
-    React.PropTypes.instanceOf(Message)
-  ]),
-
-  // An array of a certain type
-  optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
-
-  // An object with property values of a certain type
-  optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
-
-  // An object taking on a particular shape
-  optionalObjectWithShape: React.PropTypes.shape({
-    color: React.PropTypes.string,
-    fontSize: React.PropTypes.number
-  }),
-
-  // You can chain any of the above with `isRequired` to make sure a warning
-  // is shown if the prop isn't provided.
-  requiredFunc: React.PropTypes.func.isRequired,
-
-  // A value of any data type
-  requiredAny: React.PropTypes.any.isRequired,
-
-  // You can also specify a custom validator. It should return an Error
-  // object if the validation fails. Don't `console.warn` or throw, as this
-  // won't work inside `oneOfType`.
-  customProp: function(props, propName, componentName) {
-    if (!/matchme/.test(props[propName])) {
-      return new Error(
-        'Invalid prop `' + propName + '` supplied to' +
-        ' `' + componentName + '`. Validation failed.'
-      );
-    }
-  },
-
-  // You can also supply a custom validator to `arrayOf` and `objectOf`.
-  // It should return an Error object if the validation fails. The validator
-  // will be called for each key in the array or object. The first two
-  // arguments of the validator are the array or object itself, and the
-  // current item's key.
-  customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
-    if (!/matchme/.test(propValue[key])) {
-      return new Error(
-        'Invalid prop `' + propFullName + '` supplied to' +
-        ' `' + componentName + '`. Validation failed.'
-      );
-    }
-  })
-};
-

Single Child #

-

With React.PropTypes.element you can specify that only a single child can be passed to a component as children.

-
class MyComponent extends React.Component {
-  render() {
-    // This must be exactly one element or it will warn.
-    var children = this.props.children;
-    return (
-      <div>
-        {children}
-      </div>
-    );
-  }
-}
-
-MyComponent.propTypes = {
-  children: React.PropTypes.element.isRequired
-};
-

Default Prop Values #

-

React lets you define default values for your props in a very declarative way:

-
class Greeting extends React.Component {
-  render() {
-    return (
-      <h1>Hello, {this.props.name}</h1>
-    );
-  }
-}
-
-// Specifies the default values for props:
-Greeting.defaultProps = {
-  name: 'Stranger'
-};
-
-// Renders "Hello, Stranger":
-ReactDOM.render(
-  <Greeting />,
-  document.getElementById('example')
-);
-
-

The defaultProps will be used to ensure that this.props.name will have a value if it was not specified by the parent component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.

-

Transferring Props: A Shortcut #

-

A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element. To save typing, you can use the JSX spread syntax to achieve this:

-
class CheckLink extends React.Component {
-  render() {
-    // This takes any props passed to CheckLink and copies them to <a>
-    return (
-      <a {...this.props}>{'√ '}{this.props.children}</a>
-    );
-  }
-}
-
-ReactDOM.render(
-  <CheckLink href="/checked.html">
-    Click here!
-  </CheckLink>,
-  document.getElementById('example')
-);
-

Stateless Functions #

-

If a component doesn't use local state or lifecycle hooks, you can define it as a function instead of a class:

-
function Greeting(props) {
-  return <h1>Hello, {props.name}</h1>;
-}
-
-ReactDOM.render(
-  <Greeting name="Sebastian" />,
-  document.getElementById('example')
-);
-
-

Or using the new ES6 arrow syntax:

-
const Greeting = (props) => (
-  <h1>Hello, {props.name}</h1>
-);
-
-ReactDOM.render(
-  <Greeting name="Sebastian" />,
-  document.getElementById('example')
-);
-
-

This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate.

- -

However, you may still specify .propTypes and .defaultProps by setting them as properties on the function, just as you would set them on an ES6 class:

-
function Greeting(props) {
-  return (
-    <h1>Hello, {props.name}</h1>
-  );
-}
-
-Greeting.propTypes = {
-  name: React.PropTypes.string
-};
-
-Greeting.defaultProps = {
-  name: 'John Doe'
-};
-
-ReactDOM.render(
-  <Greeting name="Mădălina"/>,
-  document.getElementById('example')
-);
-
-
-

Note:

- -

Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.

-
- -

In an ideal world, many of your components would be stateless functions. In the future we plan to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.

- -

When you don't need local state or lifecycle hooks in a component, we recommend declaring it with a function. Otherwise, we recommend to use the ES6 class syntax.

-

ES6 Classes and React.createClass() #

-

Normally you would define a React component as a plain JavaScript class:

-
class Greeting extends React.Component {
-  render() {
-    return <h1>Hello, {this.props.name}</h1>;
-  }
-}
-
-

If you don't use ES6 yet, you may use React.createClass helper instead:

-
var Greeting = React.createClass({
-  render: function() {
-    return <h1>Hello, {this.props.name}</h1>;
-  }
-});
-
-

The API of ES6 classes is similar to React.createClass with a few exceptions.

-

Declaring Prop Types and Default Props #

-

With functions and ES6 classes, propTypes and defaultProps are defined as properties on the components themselves:

-
class Greeting extends React.Component {
-  // ...
-}
-
-Greeting.propTypes = {
-  name: React.PropTypes.string
-};
-
-Greeting.defaultProps = {
-  name: 'Mary'
-};
-
-

With React.createClass(), you need to define propTypes as a property on the passed object, and getDefaultProps() as a function on it:

-
var Greeting = React.createClass({
-  propTypes: {
-    name: React.PropTypes.string
-  },
-
-  getDefaultProps: function() {
-    return {
-      name: 'Mary'
-    };
-  },
-
-  // ...
-
-});
-

Setting the Initial State #

-

In ES6 classes, you can define the initial state by assigning this.state in the constructor:

-
class Counter extends React.Component {
-  constructor(props) {
-    super(props);
-    this.state = {count: props.initialCount};
-  }
-  // ...
-}
-
-

With React.createClass(), you have to provide a separate getInitialState method that returns the initial state:

-
var Counter = React.createClass({
-  getInitialState: function() {
-    return {count: this.props.initialCount};
-  },
-  // ...
-});
-

Autobinding #

-

In React components declared as ES6 classes, methods follow the same semantics as regular ES6 classes. This means that they don't automatically bind this to the instance. You'll have to explicitly use .bind(this) in the constructor:

-
class SayHello extends React.Component {
-  constructor(props) {
-    super(props);
-    // This line is important!
-    this.handleClick = this.handleClick.bind(this);
-  }
-
-  handleClick() {
-    alert('Hello!');
-  }
-
-  render() {
-    // Because `this.handleClick` is bound, we can use it as an event handler.
-    return (
-      <button onClick={this.handleClick}>
-        Say hello
-      </button>
-    );
-  }
-}
-
-

With React.createClass(), this is not necessary because it binds all methods:

-
var SayHello = React.createClass({
-  handleClick: function() {
-    alert('Hello!');
-  },
-
-  render: function() {
-    return (
-      <button onClick={this.handleClick}>
-        Say hello
-      </button>
-    );
-  }
-});
-
-

This means writing ES6 classes comes with a little more boilerplate code for event handlers, but the upside is slightly better performance in large applications.

- -

If the boilerplate code is too unattractive to you, you may enable the experimental Class Properties syntax proposal with Babel:

-
class SayHello extends React.Component {
-  // WARNING: this syntax is experimental!
-  // Using an arrow here binds the method:
-  handleClick = () => {
-    alert('Hello!');
-  }
-
-  render() {
-    return (
-      <button onClick={this.handleClick}>
-        Say hello
-      </button>
-    );
-  }
-}
-
-

Please note that the syntax above is experimental and the syntax may change, or the proposal might not make it into the language.

- -

If you'd rather play it safe, you have a few options:

- -
    -
  • Bind methods in the constructor.
  • -
  • Use arrow functions, e.g. onClick={(e) => this.handleClick(e)}).
  • -
  • Keep using React.createClass().
  • -
-

Mixins #

-
-

Note:

- -

ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes.

- -

We also found numerous issues in codebases using mixins, and don't recommend using them in the new code.

- -

This section exists only for the reference.

-
- -

Sometimes very different components may share some common functionality. These are sometimes called cross-cutting concerns. React.createClass lets you use a legacy mixins system for that.

- -

One common use case is a component wanting to update itself on a time interval. It's easy to use setInterval(), but it's important to cancel your interval when you don't need it anymore to save memory. React provides lifecycle methods that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy setInterval() function that will automatically get cleaned up when your component is destroyed.

-
var SetIntervalMixin = {
-  componentWillMount: function() {
-    this.intervals = [];
-  },
-  setInterval: function() {
-    this.intervals.push(setInterval.apply(null, arguments));
-  },
-  componentWillUnmount: function() {
-    this.intervals.forEach(clearInterval);
-  }
-};
-
-var TickTock = React.createClass({
-  mixins: [SetIntervalMixin], // Use the mixin
-  getInitialState: function() {
-    return {seconds: 0};
-  },
-  componentDidMount: function() {
-    this.setInterval(this.tick, 1000); // Call a method on the mixin
-  },
-  tick: function() {
-    this.setState({seconds: this.state.seconds + 1});
-  },
-  render: function() {
-    return (
-      <p>
-        React has been running for {this.state.seconds} seconds.
-      </p>
-    );
-  }
-});
-
-ReactDOM.render(
-  <TickTock />,
-  document.getElementById('example')
-);
-
-

If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/shallow-compare-zh-CN.html b/docs/shallow-compare-zh-CN.html deleted file mode 100644 index a8bbbbfa98..0000000000 --- a/docs/shallow-compare-zh-CN.html +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - - 浅比较 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 浅比较 -

-
- -

shallowCompare 是一个辅助函数 在以ES6类使用React时,完成和 PureRenderMixin 相同的功能。

- -

如果你的React组件的绘制函数是 “干净的” (换句话说,它在给定的 props 和 state 下绘制相同的结果),你可以使用这个辅助函数以在某些情况下提升性能。

- -

例如:

-
var shallowCompare = require('react-addons-shallow-compare');
-export class SampleComponent extends React.Component {
-  shouldComponentUpdate(nextProps, nextState) {
-    return shallowCompare(this, nextProps, nextState);
-  }
-
-  render() {
-    return <div className={this.props.className}>foo</div>;
-  }
-}
-
-

shallowCompare 对当前的 propsnextProps对象 执行一个浅的相等检查,同样对于 statenextState对象。 -它 通过迭代比较对象的keys 并在 对象的key值不严格相等时返回false 实现此功能.

- -

shallowCompare 返回 true 如果对 props 或 state的浅比较失败,因此组件应该更新。 -shallowCompare 返回 false 如果对 props 或 state的浅比较都通过了,因此组件不应该更新。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/shallow-compare.html b/docs/shallow-compare.html index 5dd3efd81e..9048474d82 100644 --- a/docs/shallow-compare.html +++ b/docs/shallow-compare.html @@ -1,12 +1,14 @@ + + - Shallow Compare | React - - + Shallow Compare - React + + @@ -44,31 +46,76 @@
-
+
+ Edit on GitHub +

+ Shallow Compare +

+
+ +
+

Note: +shallowCompare is a legacy add-on. Use React.PureComponent instead.

+
+ +

Importing

+
import shallowCompare from 'react-addons-shallow-compare' // ES6
+var shallowCompare = require('react-addons-shallow-compare') // ES5 with npm
+var shallowCompare = React.addons.shallowCompare; // ES5 with react-with-addons.js
+

Overview #

+

Before React.PureComponent was introduced, shallowCompare was commonly used to achieve the same functionality as PureRenderMixin while using ES6 classes with React.

+ +

If your React component's render function is "pure" (in other words, it renders the same result given the same props and state), you can use this helper function for a performance boost in some cases.

+ +

Example:

+
export class SampleComponent extends React.Component {
+  shouldComponentUpdate(nextProps, nextState) {
+    return shallowCompare(this, nextProps, nextState);
+  }
+
+  render() {
+    return <div className={this.props.className}>foo</div>;
+  }
+}
+
+

shallowCompare performs a shallow equality check on the current props and nextProps objects as well as the current state and nextState objects.
+It does this by iterating on the keys of the objects being compared and returning true when the values of a key in each object are not strictly equal.

+ +

shallowCompare returns true if the shallow comparison for props or state fails and therefore the component should update.
+shallowCompare returns false if the shallow comparison for props and state both pass and therefore the component does not need to update.

+ + +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,64 +350,57 @@
+ - -
- Edit on GitHub -

- Shallow Compare -

-
- -

shallowCompare is a helper function to achieve the same functionality as PureRenderMixin while using ES6 classes with React.

- -

If your React component's render function is "pure" (in other words, it renders the same result given the same props and state), you can use this helper function for a performance boost in some cases.

- -

Example:

-
var shallowCompare = require('react-addons-shallow-compare');
-export class SampleComponent extends React.Component {
-  shouldComponentUpdate(nextProps, nextState) {
-    return shallowCompare(this, nextProps, nextState);
-  }
-
-  render() {
-    return <div className={this.props.className}>foo</div>;
-  }
-}
-
-

shallowCompare performs a shallow equality check on the current props and nextProps objects as well as the current state and nextState objects.
-It does this by iterating on the keys of the objects being compared and returning true when the values of a key in each object are not strictly equal.

- -

shallowCompare returns true if the shallow comparison for props or state fails and therefore the component should update.
-shallowCompare returns false if the shallow comparison for props and state both pass and therefore the component does not need to update.

- - -
- - ← Prev - - - Next → - -
-
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
- -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Attributi Speciali Non-DOM -

-
- -

Oltre alle Differenze del DOM, React offre alcuni attributi che semplicemente non esistono nel DOM.

- -
    -
  • key: un identificatore univoco opzionale. Quando il tuo componente viene riordinato durante i passaggi di render, potrebbe essere distrutto e ricreato in base all'algoritmo di calcolo delle differenze. Assegnargli una chiave che persiste assicura che il componente venga preservato. Scopri maggiori dettagli qui.
  • -
  • ref: leggi qui.
  • -
  • dangerouslySetInnerHTML: Offre l'abilità di inserire HTML grezzo, principalmente per cooperare con librerie di manipolazione di stringhe DOM. Scopri maggiori dettagli qui.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/special-non-dom-attributes-ko-KR.html b/docs/special-non-dom-attributes-ko-KR.html deleted file mode 100644 index 2405845f9f..0000000000 --- a/docs/special-non-dom-attributes-ko-KR.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - DOM이 아닌 특별한 어트리뷰트 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- DOM이 아닌 특별한 어트리뷰트 -

-
- -

DOM 차이점처럼, React는 DOM에는 존재하지 않는 몇몇 어트리뷰트도 제공합니다.

- -
    -
  • key: 선택적인 고유 식별자. 컴포넌트가 render 과정에서 섞일 때, diff 알고리즘에 의해 파괴되고, 다시 생성될 수 있습니다. 컴포넌트에 영속적인(persists) 키를 할당하면 컴포넌트가 확실히 유지되게 할 수 있습니다. 더 자세한 것은 여기에서 보세요.
  • -
  • ref: 여기를 보세요.
  • -
  • dangerouslySetInnerHTML: 생(raw) HTML을 넣을 수 있게 합니다. 주로 DOM 문자열 관리 라이브러리와의 협력하기 위해 사용합니다. 더 자세한 것은 여기를 보세요.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/special-non-dom-attributes-zh-CN.html b/docs/special-non-dom-attributes-zh-CN.html deleted file mode 100644 index fc46fea179..0000000000 --- a/docs/special-non-dom-attributes-zh-CN.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - 特殊的 Non-DOM Attributes | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 特殊的 Non-DOM Attributes -

-
- -

DOM 的不同之处相比, React 提供了一些不存在于DOM的 attributes .

- -
    -
  • key: 一个可选的.独特的标识.当你的组件穿梭于 render 的pass,它也许会因为diff算法被摧毁和重建.赋予它一个持久的key保证这个component可达.详见 这里.
  • -
  • ref: 见 这里.
  • -
  • dangerouslySetInnerHTML: 提供了直接插入raw HTML的能力,主要是为了与操纵DOM字符串的库协作.详见 这里.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/special-non-dom-attributes.html b/docs/special-non-dom-attributes.html deleted file mode 100644 index c248e144b9..0000000000 --- a/docs/special-non-dom-attributes.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - Special Non-DOM Attributes | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Special Non-DOM Attributes -

-
- -

Beside DOM differences, React offers some attributes that simply don't exist in DOM.

- -
    -
  • key: an optional, unique identifier. When your component shuffles around during render passes, it might be destroyed and recreated due to the diff algorithm. Assigning it a key that persists makes sure the component stays. See more here.
  • -
  • ref: see here.
  • -
  • dangerouslySetInnerHTML: Provides the ability to insert raw HTML, mainly for cooperating with DOM string manipulation libraries. See more here.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/state-and-lifecycle.html b/docs/state-and-lifecycle.html new file mode 100644 index 0000000000..61cfe4cf3d --- /dev/null +++ b/docs/state-and-lifecycle.html @@ -0,0 +1,762 @@ + + + + + + + + + State and Lifecycle - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ State and Lifecycle +

+
+ +

Consider the ticking clock example from the one of the previous sections.

+ +

So far we have only learned one way to update the UI.

+ +

We call ReactDOM.render() to change the rendered output:

+
function tick() {
+  const element = (
+    <div>
+      <h1>Hello, world!</h1>
+      <h2>It is {new Date().toLocaleTimeString()}.</h2>
+    </div>
+  );
+  ReactDOM.render(
+    element,
+    document.getElementById('root')
+  );
+}
+
+setInterval(tick, 1000);
+
+

Try it on CodePen.

+ +

In this section, we will learn how to make the Clock component truly reusable and encapsulated. It will set up its own timer and update itself every second.

+ +

We can start by encapsulating how the clock looks:

+
function Clock(props) {
+  return (
+    <div>
+      <h1>Hello, world!</h1>
+      <h2>It is {props.date.toLocaleTimeString()}.</h2>
+    </div>
+  );
+}
+
+function tick() {
+  ReactDOM.render(
+    <Clock date={new Date()} />,
+    document.getElementById('root')
+  );
+}
+
+setInterval(tick, 1000);
+
+

Try it on CodePen.

+ +

However, it misses a crucial requirement: the fact that the Clock sets up a timer and updates the UI every second should be an implementation detail of the Clock.

+ +

Ideally we want to write this once and have the Clock update itself:

+
ReactDOM.render(
+  <Clock />,
+  document.getElementById('root')
+);
+
+

To implement this, we need to add "state" to the Clock component.

+ +

State is similar to props, but it is private and fully controlled by the component.

+ +

We mentioned before that components defined as classes have some additional features. Local state is exactly that: a feature available only to classes.

+

Converting a Function to a Class #

+

You can convert a functional component like Clock to a class in five steps:

+ +
    +
  1. Create an ES6 class with the same name that extends React.Component.

  2. +
  3. Add a single empty method to it called render().

  4. +
  5. Move the body of the function into the render() method.

  6. +
  7. Replace props with this.props in the render() body.

  8. +
  9. Delete the remaining empty function declaration.

  10. +
+
class Clock extends React.Component {
+  render() {
+    return (
+      <div>
+        <h1>Hello, world!</h1>
+        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
+      </div>
+    );
+  }
+}
+
+

Try it on CodePen.

+ +

Clock is now defined as a class rather than a function.

+ +

This lets us use additional features such as local state and lifecycle hooks.

+

Adding Local State to a Class #

+

We will move the date from props to state in three steps:

+ +

1) Replace this.props.date with this.state.date in the render() method:

+
class Clock extends React.Component {
+  render() {
+    return (
+      <div>
+        <h1>Hello, world!</h1>
+        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
+      </div>
+    );
+  }
+}
+
+

2) Add a class constructor that assigns the initial this.state:

+
class Clock extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {date: new Date()};
+  }
+
+  render() {
+    return (
+      <div>
+        <h1>Hello, world!</h1>
+        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
+      </div>
+    );
+  }
+}
+
+

Note how we pass props to the base constructor:

+
  constructor(props) {
+    super(props);
+    this.state = {date: new Date()};
+  }
+
+

Class components should always call the base constructor with props.

+ +

3) Remove the date prop from the <Clock /> element:

+
ReactDOM.render(
+  <Clock />,
+  document.getElementById('root')
+);
+
+

We will later add the timer code back to the component itself.

+ +

The result looks like this:

+
class Clock extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {date: new Date()};
+  }
+
+  render() {
+    return (
+      <div>
+        <h1>Hello, world!</h1>
+        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
+      </div>
+    );
+  }
+}
+
+ReactDOM.render(
+  <Clock />,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

Next, we'll make the Clock set up its own timer and update itself every second.

+

Adding Lifecycle Methods to a Class #

+

In applications with many components, it's very important to free up resources taken by the components when they are destroyed.

+ +

We want to set up a timer whenever the Clock is rendered to the DOM for the first time. This is called "mounting" in React.

+ +

We also want to clear that timer whenever the DOM produced by the Clock is removed. This is called "unmounting" in React.

+ +

We can declare special methods on the component class to run some code when a component mounts and unmounts:

+
class Clock extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {date: new Date()};
+  }
+
+  componentDidMount() {
+
+  }
+
+  componentWillUnmount() {
+
+  }
+
+  render() {
+    return (
+      <div>
+        <h1>Hello, world!</h1>
+        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
+      </div>
+    );
+  }
+}
+
+

These methods are called "lifecycle hooks".

+ +

The componentDidMount() hook runs after the component output has been rendered to the DOM. This is a good place to set up a timer:

+
  componentDidMount() {
+    this.timerID = setInterval(
+      () => this.tick(),
+      1000
+    );
+  }
+
+

Note how we save the timer ID right on this.

+ +

While this.props is set up by React itself and this.state has a special meaning, you are free to add additional fields to the class manually if you need to store something that is not used for the visual output.

+ +

If you don't use something in render(), it shouldn't be in the state.

+ +

We will tear down the timer in the componentWillUnmount() lifecycle hook:

+
  componentWillUnmount() {
+    clearInterval(this.timerID);
+  }
+
+

Finally, we will implement the tick() method that runs every second.

+ +

It will use this.setState() to schedule updates to the component local state:

+
class Clock extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {date: new Date()};
+  }
+
+  componentDidMount() {
+    this.timerID = setInterval(
+      () => this.tick(),
+      1000
+    );
+  }
+
+  componentWillUnmount() {
+    clearInterval(this.timerID);
+  }
+
+  tick() {
+    this.setState({
+      date: new Date()
+    });
+  }
+
+  render() {
+    return (
+      <div>
+        <h1>Hello, world!</h1>
+        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
+      </div>
+    );
+  }
+}
+
+ReactDOM.render(
+  <Clock />,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

Now the clock ticks every second.

+

Using State Correctly #

+

There are three things you should know about setState().

+

Do Not Modify State Directly #

+

For example, this will not re-render a component:

+
// Wrong
+this.state.comment = 'Hello';
+
+

Instead, use setState():

+
// Correct
+this.setState({comment: 'Hello'});
+

State Updates May Be Asynchronous #

+

React may batch multiple setState() calls into a single update for performance.

+ +

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

+ +

For example, this code may fail to update the counter:

+
// Wrong
+this.setState({
+  counter: this.state.counter + this.props.increment,
+});
+
+

To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:

+
// Correct
+this.setState((prevState, props) => ({
+  counter: prevState.counter + props.increment
+}));
+
+

We used an arrow function above, but it also works with regular functions:

+
// Correct
+this.setState(function(prevState, props) {
+  return {
+    counter: prevState.counter + props.increment
+  };
+});
+

State Updates are Merged #

+

When you call setState(), React merges the object you provide into the current state.

+ +

For example, your state may contain several independent variables:

+
  constructor(props) {
+    super(props);
+    this.state = {
+      posts: [],
+      comments: []
+    };
+  }
+
+

Then you can update them independently with separate setState() calls:

+
  componentDidMount() {
+    fetchPosts().then(response => {
+      this.setState({
+        posts: response.posts
+      });
+    });
+
+    fetchComments().then(response => {
+      this.setState({
+        comments: response.comments
+      });
+    });
+  }
+
+

The merging is shallow, so this.setState({comments}) leaves this.state.posts intact, but completely replaces this.state.comments.

+

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.

+ +

This is why state is often called local or encapsulated. It is not accessible to any component other than the one that owns and sets it.

+ +

A component may choose to pass its state down as props to its child components:

+
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
+
+

This also works for user-defined components:

+
<FormattedDate date={this.state.date} />
+
+

The FormattedDate component would receive the date in its props and wouldn't know whether it came from the Clock's state, the props, or was typed by hand:

+
function FormattedDate(props) {
+  return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
+}
+
+

Try it on CodePen.

+ +

This is commonly called a "top-down" or "unidirectional" data flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components "below" them in the tree.

+ +

If you imagine a component tree as a waterfall of props, each component's state is like an additional water source that joins it at an arbitrary point but also flows down.

+ +

To show that all components are truly isolated, we can create an App component that renders three <Clock>s:

+
function App() {
+  return (
+    <div>
+      <Clock />
+      <Clock />
+      <Clock />
+    </div>
+  );
+}
+
+ReactDOM.render(
+  <App />,
+  document.getElementById('root')
+);
+
+

Try it on CodePen.

+ +

Each Clock sets up its own timer and updates independently.

+ +

In React apps, whether a component is stateful or stateless is considered an implementation detail of the component that may change over time. You can use stateless components inside stateful components, and vice versa.

+ + +
+ + ← Prev + + + Next → + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/tags-and-attributes-it-IT.html b/docs/tags-and-attributes-it-IT.html deleted file mode 100644 index 70e6a8fed8..0000000000 --- a/docs/tags-and-attributes-it-IT.html +++ /dev/null @@ -1,587 +0,0 @@ - - - - - - - Tag e Attributi | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Tag e Attributi -

-
- -

Tag Supportati #

-

React tenta di supportare tutti gli elementi comuni. Se hai bisogno di un elemento che non è elencato di seguito, per favore apri una issue.

-

Elementi HTML #

-

I seguenti elementi HTML sono supportati:

-
a abbr address area article aside audio b base bdi bdo big blockquote body br
-button canvas caption cite code col colgroup data datalist dd del details dfn
-dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
-h6 head header hr html i iframe img input ins kbd keygen label legend li link
-main map mark menu menuitem meta meter nav noscript object ol optgroup option
-output p param picture pre progress q rp rt ruby s samp script section select
-small source span strong style sub summary sup table tbody td textarea tfoot th
-thead time title tr track u ul var video wbr
-

Elementi SVG #

-

I seguenti elementi SVG sono supportati:

-
circle clipPath defs ellipse g line linearGradient mask path pattern polygon polyline
-radialGradient rect stop svg text tspan
-
-

Potresti trovare utile react-art, una libreria di disegno per React che può disegnare su Canvas, SVG oppure VML (per IE8).

-

Attributi Supportati #

-

React supporta tutti gli attributi data-* e aria-*, oltre a ciascun attributo nelle liste seguenti.

- -
-

Nota:

- -

Tutti gli attributi sono camel-cased, e gli attributi class e for sono resi come className e htmlFor rispettivamente, per adeguarsi alla specifica delle API del DOM.

-
- -

Per una lista di eventi, consulta gli Eventi Supportati.

-

Attributi HTML #

-

Questi attributi standard sono supportati:

-
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
-async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
-charSet checked cite classID className colSpan cols content contentEditable
-contextMenu controls coords crossOrigin data dateTime default defer dir
-disabled download draggable encType form formAction formEncType formMethod
-formNoValidate formTarget frameBorder headers height hidden high href hrefLang
-htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
-lang list loop low manifest marginHeight marginWidth max maxLength media
-mediaGroup method min minLength multiple muted name noValidate nonce open
-optimum pattern placeholder poster preload profile radioGroup readOnly rel
-required reversed role rowSpan rows sandbox scope scoped scrolling seamless
-selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step
-style summary tabIndex target title type useMap value width wmode wrap
-
-

In aggiunta, i seguenti attributi non-standard sono supportati:

- -
    -
  • autoCapitalize autoCorrect per Mobile Safari.
  • -
  • property per i meta tag Open Graph.
  • -
  • itemProp itemScope itemType itemRef itemID per i microdata HTML5.
  • -
  • unselectable per Internet Explorer.
  • -
  • results autoSave per campi di input del tipo search in WebKit/Blink.
  • -
- -

Esiste anche l'attributo specifico di React dangerouslySetInnerHTML (maggiori informazioni), usato per inserire direttamente stringhe di HTML in un componente.

-

Attributi SVG #

accentHeight accumulate additive alignmentBaseline allowReorder alphabetic
-amplitude arabicForm ascent attributeName attributeType autoReverse azimuth
-baseFrequency baseProfile baselineShift bbox begin bias by calcMode capHeight
-clip clipPath clipPathUnits clipRule colorInterpolation
-colorInterpolationFilters colorProfile colorRendering contentScriptType
-contentStyleType cursor cx cy d decelerate descent diffuseConstant direction
-display divisor dominantBaseline dur dx dy edgeMode elevation enableBackground
-end exponent externalResourcesRequired fill fillOpacity fillRule filter
-filterRes filterUnits floodColor floodOpacity focusable fontFamily fontSize
-fontSizeAdjust fontStretch fontStyle fontVariant fontWeight format from fx fy
-g1 g2 glyphName glyphOrientationHorizontal glyphOrientationVertical glyphRef
-gradientTransform gradientUnits hanging horizAdvX horizOriginX ideographic
-imageRendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength
-kerning keyPoints keySplines keyTimes lengthAdjust letterSpacing lightingColor
-limitingConeAngle local markerEnd markerHeight markerMid markerStart
-markerUnits markerWidth mask maskContentUnits maskUnits mathematical mode
-numOctaves offset opacity operator order orient orientation origin overflow
-overlinePosition overlineThickness paintOrder panose1 pathLength
-patternContentUnits patternTransform patternUnits pointerEvents points
-pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits
-r radius refX refY renderingIntent repeatCount repeatDur requiredExtensions
-requiredFeatures restart result rotate rx ry scale seed shapeRendering slope
-spacing specularConstant specularExponent speed spreadMethod startOffset
-stdDeviation stemh stemv stitchTiles stopColor stopOpacity
-strikethroughPosition strikethroughThickness string stroke strokeDasharray
-strokeDashoffset strokeLinecap strokeLinejoin strokeMiterlimit strokeOpacity
-strokeWidth surfaceScale systemLanguage tableValues targetX targetY textAnchor
-textDecoration textLength textRendering to transform u1 u2 underlinePosition
-underlineThickness unicode unicodeBidi unicodeRange unitsPerEm vAlphabetic
-vHanging vIdeographic vMathematical values vectorEffect version vertAdvY
-vertOriginX vertOriginY viewBox viewTarget visibility widths wordSpacing
-writingMode x x1 x2 xChannelSelector xHeight xlinkActuate xlinkArcrole
-xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace
-y y1 y2 yChannelSelector z zoomAndPan
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tags-and-attributes-ko-KR.html b/docs/tags-and-attributes-ko-KR.html deleted file mode 100644 index 1cee883cf4..0000000000 --- a/docs/tags-and-attributes-ko-KR.html +++ /dev/null @@ -1,587 +0,0 @@ - - - - - - - 태그와 어트리뷰트 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 태그와 어트리뷰트 -

-
- -

지원되는 태그 #

-

React는 모든 공통 엘리먼트를 지원하려 합니다. 필요한 엘리먼트가 목록에 없다면, 이슈로 등록해 주세요.

-

HTML 엘리먼트 #

-

다음의 HTML 엘리먼트가 지원됩니다.

-
a abbr address area article aside audio b base bdi bdo big blockquote body br
-button canvas caption cite code col colgroup data datalist dd del details dfn
-dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
-h6 head header hr html i iframe img input ins kbd keygen label legend li link
-main map mark menu menuitem meta meter nav noscript object ol optgroup option
-output p param picture pre progress q rp rt ruby s samp script section select
-small source span strong style sub summary sup table tbody td textarea tfoot th
-thead time title tr track u ul var video wbr
-

SVG 엘리먼트 #

-

다음의 SVG 엘리먼트가 지원됩니다.

-
circle clipPath defs ellipse g line linearGradient mask path pattern polygon polyline
-radialGradient rect stop svg text tspan
-
-

아마 Canvas, SVG, VML(IE8 전용)에 렌더할 때 쓰는 React의 드로잉 라이브러리인 react-art도 흥미 있으실 수 있습니다.

-

지원되는 어트리뷰트 #

-

React는 모든 data-*, aria-* 어트리뷰트와 밑에 있는 모든 어트리뷰트를 지원합니다.

- -
-

주의:

- -

모든 어트리뷰트는 카멜케이스이고, class for 어트리뷰트는 각각 DOM API의 사양에 맞춰서 className htmlFor 가 됩니다.

-
- -

이벤트의 목록을 보시려면 지원되는 이벤트를 확인하세요.

-

HTML 어트리뷰트 #

-

이런 표준 어트리뷰트가 지원됩니다.

-
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
-async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
-charSet checked cite classID className colSpan cols content contentEditable
-contextMenu controls coords crossOrigin data dateTime default defer dir
-disabled download draggable encType form formAction formEncType formMethod
-formNoValidate formTarget frameBorder headers height hidden high href hrefLang
-htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
-lang list loop low manifest marginHeight marginWidth max maxLength media
-mediaGroup method min minLength multiple muted name noValidate nonce open
-optimum pattern placeholder poster preload profile radioGroup readOnly rel
-required reversed role rowSpan rows sandbox scope scoped scrolling seamless
-selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step
-style summary tabIndex target title type useMap value width wmode wrap
-
-

덧붙여, 이런 비표준 어트리뷰트도 지원됩니다.

- -
    -
  • 모바일 사파리를 위한 autoCapitalize autoCorrect.
  • -
  • 오픈 그래프 메타 태그를 위한 property.
  • -
  • HTML5 마이크로데이터를 위한 itemProp itemScope itemType itemRef itemID.
  • -
  • 인터넷 익스플로어를 위한 unselectable.
  • -
  • WebKit/Blink의 search 타입 input 필드를 위한 results autoSave
  • -
- -

컴포넌트에 직접 HTML 문자열을 넣을 때 사용하는, React 전용 어트리뷰트 dangerouslySetInnerHTML(자세한 정보는 여기)도 있습니다.

-

SVG 어트리뷰트 #

accentHeight accumulate additive alignmentBaseline allowReorder alphabetic
-amplitude arabicForm ascent attributeName attributeType autoReverse azimuth
-baseFrequency baseProfile baselineShift bbox begin bias by calcMode capHeight
-clip clipPath clipPathUnits clipRule colorInterpolation
-colorInterpolationFilters colorProfile colorRendering contentScriptType
-contentStyleType cursor cx cy d decelerate descent diffuseConstant direction
-display divisor dominantBaseline dur dx dy edgeMode elevation enableBackground
-end exponent externalResourcesRequired fill fillOpacity fillRule filter
-filterRes filterUnits floodColor floodOpacity focusable fontFamily fontSize
-fontSizeAdjust fontStretch fontStyle fontVariant fontWeight format from fx fy
-g1 g2 glyphName glyphOrientationHorizontal glyphOrientationVertical glyphRef
-gradientTransform gradientUnits hanging horizAdvX horizOriginX ideographic
-imageRendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength
-kerning keyPoints keySplines keyTimes lengthAdjust letterSpacing lightingColor
-limitingConeAngle local markerEnd markerHeight markerMid markerStart
-markerUnits markerWidth mask maskContentUnits maskUnits mathematical mode
-numOctaves offset opacity operator order orient orientation origin overflow
-overlinePosition overlineThickness paintOrder panose1 pathLength
-patternContentUnits patternTransform patternUnits pointerEvents points
-pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits
-r radius refX refY renderingIntent repeatCount repeatDur requiredExtensions
-requiredFeatures restart result rotate rx ry scale seed shapeRendering slope
-spacing specularConstant specularExponent speed spreadMethod startOffset
-stdDeviation stemh stemv stitchTiles stopColor stopOpacity
-strikethroughPosition strikethroughThickness string stroke strokeDasharray
-strokeDashoffset strokeLinecap strokeLinejoin strokeMiterlimit strokeOpacity
-strokeWidth surfaceScale systemLanguage tableValues targetX targetY textAnchor
-textDecoration textLength textRendering to transform u1 u2 underlinePosition
-underlineThickness unicode unicodeBidi unicodeRange unitsPerEm vAlphabetic
-vHanging vIdeographic vMathematical values vectorEffect version vertAdvY
-vertOriginX vertOriginY viewBox viewTarget visibility widths wordSpacing
-writingMode x x1 x2 xChannelSelector xHeight xlinkActuate xlinkArcrole
-xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace
-y y1 y2 yChannelSelector z zoomAndPan
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tags-and-attributes-zh-CN.html b/docs/tags-and-attributes-zh-CN.html deleted file mode 100644 index da36988238..0000000000 --- a/docs/tags-and-attributes-zh-CN.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - Tags和属性 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Tags和属性 -

-
- -

支持的Tags #

-

React试着支持所有常见的元素.如果你需要一个没有列在这里的元素,请 file an issue.

-

HTML 元素 #

-

下面的HTML是被支持的:

-
a abbr address area article aside audio b base bdi bdo big blockquote body br
-button canvas caption cite code col colgroup data datalist dd del details dfn
-dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
-h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li
-link main map mark menu menuitem meta meter nav noscript object ol optgroup
-option output p param picture pre progress q rp rt ruby s samp script section
-select small source span strong style sub summary sup table tbody td textarea
-tfoot th thead time title tr track u ul var video wbr
-

SVG 元素 #

-

下面的 SVG 元素是被支持的:

-
circle clipPath defs ellipse g image line linearGradient mask path pattern
-polygon polyline radialGradient rect stop svg text tspan
-
-

你也许对 react-art有兴趣,一个让React绘制Canvas, SVG, 或者 VML (for IE8) 的绘制库.

-

支持的属性 #

-

React支持所有的 data-*aria-* 以及下列的属性.

- -
-

注意:

- -

所有的属性都是 camel-cased ,classfor 分别是 classNamehtmlFor,来符合DOM API 规范.

-
- -

关于事件的列表,见 Supported Events.

-

HTML 属性 #

-

下面的标准属性是被支持的:

-
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
-async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
-charSet checked cite classID className colSpan cols content contentEditable
-contextMenu controls coords crossOrigin data dateTime default defer dir
-disabled download draggable encType form formAction formEncType formMethod
-formNoValidate formTarget frameBorder headers height hidden high href hrefLang
-htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
-lang list loop low manifest marginHeight marginWidth max maxLength media
-mediaGroup method min minLength multiple muted name noValidate nonce open
-optimum pattern placeholder poster preload profile radioGroup readOnly rel
-required reversed role rowSpan rows sandbox scope scoped scrolling seamless
-selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step
-style summary tabIndex target title type useMap value width wmode wrap
-
-

这些RDFa属性是被支持的 (许多RDFa属性和标准的HTML属性重叠,因此被从这个列表里去除):

-
about datatype inlist prefix property resource typeof vocab
-
-

另外,支持下面的非标准属性:

- -
    -
  • autoCapitalize autoCorrect for Mobile Safari.
  • -
  • color for <link rel="mask-icon" /> in Safari.
  • -
  • itemProp itemScope itemType itemRef itemID for HTML5 microdata.
  • -
  • security 老的IE浏览器.
  • -
  • unselectable IE浏览器.
  • -
  • results autoSave for WebKit/Blink input fields of type search.
  • -
- -

同样有React规范的属性 dangerouslySetInnerHTML (more here),用于直接插入HTML字符串到组件里.

-

SVG 属性 #

accentHeight accumulate additive alignmentBaseline allowReorder alphabetic
-amplitude arabicForm ascent attributeName attributeType autoReverse azimuth
-baseFrequency baseProfile baselineShift bbox begin bias by calcMode capHeight
-clip clipPath clipPathUnits clipRule colorInterpolation
-colorInterpolationFilters colorProfile colorRendering contentScriptType
-contentStyleType cursor cx cy d decelerate descent diffuseConstant direction
-display divisor dominantBaseline dur dx dy edgeMode elevation enableBackground
-end exponent externalResourcesRequired fill fillOpacity fillRule filter
-filterRes filterUnits floodColor floodOpacity focusable fontFamily fontSize
-fontSizeAdjust fontStretch fontStyle fontVariant fontWeight format from fx fy
-g1 g2 glyphName glyphOrientationHorizontal glyphOrientationVertical glyphRef
-gradientTransform gradientUnits hanging horizAdvX horizOriginX ideographic
-imageRendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength
-kerning keyPoints keySplines keyTimes lengthAdjust letterSpacing lightingColor
-limitingConeAngle local markerEnd markerHeight markerMid markerStart
-markerUnits markerWidth mask maskContentUnits maskUnits mathematical mode
-numOctaves offset opacity operator order orient orientation origin overflow
-overlinePosition overlineThickness paintOrder panose1 pathLength
-patternContentUnits patternTransform patternUnits pointerEvents points
-pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits
-r radius refX refY renderingIntent repeatCount repeatDur requiredExtensions
-requiredFeatures restart result rotate rx ry scale seed shapeRendering slope
-spacing specularConstant specularExponent speed spreadMethod startOffset
-stdDeviation stemh stemv stitchTiles stopColor stopOpacity
-strikethroughPosition strikethroughThickness string stroke strokeDasharray
-strokeDashoffset strokeLinecap strokeLinejoin strokeMiterlimit strokeOpacity
-strokeWidth surfaceScale systemLanguage tableValues targetX targetY textAnchor
-textDecoration textLength textRendering to transform u1 u2 underlinePosition
-underlineThickness unicode unicodeBidi unicodeRange unitsPerEm vAlphabetic
-vHanging vIdeographic vMathematical values vectorEffect version vertAdvY
-vertOriginX vertOriginY viewBox viewTarget visibility widths wordSpacing
-writingMode x x1 x2 xChannelSelector xHeight xlinkActuate xlinkArcrole
-xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace
-y y1 y2 yChannelSelector z zoomAndPan
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tags-and-attributes.html b/docs/tags-and-attributes.html deleted file mode 100644 index 7e276aec66..0000000000 --- a/docs/tags-and-attributes.html +++ /dev/null @@ -1,595 +0,0 @@ - - - - - - - Tags and Attributes | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Tags and Attributes -

-
- -

Supported Elements #

-

React attempts to support all common elements in both HTML and SVG. Any lower case tag in JSX will be rendered to an element with that tag. SVG elements must be contained within an <svg> element to work properly.

-

Using React.DOM Factory methods #

-

If you aren't using JSX and are using the React.DOM.* API to create elements, then you are slightly more limited and there is list of supported elements that will be available on that API.

-

HTML Elements #

-

The following HTML elements are supported in React.DOM.*:

-
a abbr address area article aside audio b base bdi bdo big blockquote body br
-button canvas caption cite code col colgroup data datalist dd del details dfn
-dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
-h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li
-link main map mark menu menuitem meta meter nav noscript object ol optgroup
-option output p param picture pre progress q rp rt ruby s samp script section
-select small source span strong style sub summary sup table tbody td textarea
-tfoot th thead time title tr track u ul var video wbr
-

SVG elements #

-

The following SVG elements are supported in React.DOM.*:

-
circle clipPath defs ellipse g image line linearGradient mask path pattern
-polygon polyline radialGradient rect stop svg text tspan
-
-

You may also be interested in react-art, a cross-browser drawing library for React.

-

Supported Attributes #

-

React supports all data-* and aria-* attributes as well as every attribute in the following lists.

- -
-

Note:

- -

All attributes are camel-cased and the attributes class and for are className and htmlFor, respectively, to match the DOM API specification.

-
- -

For a list of events, see Supported Events.

-

HTML Attributes #

-

These standard attributes are supported:

-
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
-async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
-charSet checked cite classID className colSpan cols content contentEditable
-contextMenu controls coords crossOrigin data dateTime default defer dir
-disabled download draggable encType form formAction formEncType formMethod
-formNoValidate formTarget frameBorder headers height hidden high href hrefLang
-htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
-lang list loop low manifest marginHeight marginWidth max maxLength media
-mediaGroup method min minLength multiple muted name noValidate nonce open
-optimum pattern placeholder poster preload profile radioGroup readOnly rel
-required reversed role rowSpan rows sandbox scope scoped scrolling seamless
-selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step
-style summary tabIndex target title type useMap value width wmode wrap
-
-

These RDFa attributes are supported (several RDFa attributes overlap with standard HTML attributes and thus are excluded from this list):

-
about datatype inlist prefix property resource typeof vocab
-
-

In addition, the following non-standard attributes are supported:

- -
    -
  • autoCapitalize autoCorrect for Mobile Safari.
  • -
  • color for <link rel="mask-icon" /> in Safari.
  • -
  • itemProp itemScope itemType itemRef itemID for HTML5 microdata.
  • -
  • security for older versions of Internet Explorer.
  • -
  • unselectable for Internet Explorer.
  • -
  • results autoSave for WebKit/Blink input fields of type search.
  • -
- -

There is also 2 React-specific attributes: -- dangerouslySetInnerHTML (more here), used for directly inserting HTML strings into a component. -- suppressContentEditableWarning, used to suppress the warning when using contentEditable and children.

-

SVG Attributes #

accentHeight accumulate additive alignmentBaseline allowReorder alphabetic
-amplitude arabicForm ascent attributeName attributeType autoReverse azimuth
-baseFrequency baseProfile baselineShift bbox begin bias by calcMode capHeight
-clip clipPath clipPathUnits clipRule colorInterpolation
-colorInterpolationFilters colorProfile colorRendering contentScriptType
-contentStyleType cursor cx cy d decelerate descent diffuseConstant direction
-display divisor dominantBaseline dur dx dy edgeMode elevation enableBackground
-end exponent externalResourcesRequired fill fillOpacity fillRule filter
-filterRes filterUnits floodColor floodOpacity focusable fontFamily fontSize
-fontSizeAdjust fontStretch fontStyle fontVariant fontWeight format from fx fy
-g1 g2 glyphName glyphOrientationHorizontal glyphOrientationVertical glyphRef
-gradientTransform gradientUnits hanging horizAdvX horizOriginX ideographic
-imageRendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength
-kerning keyPoints keySplines keyTimes lengthAdjust letterSpacing lightingColor
-limitingConeAngle local markerEnd markerHeight markerMid markerStart
-markerUnits markerWidth mask maskContentUnits maskUnits mathematical mode
-numOctaves offset opacity operator order orient orientation origin overflow
-overlinePosition overlineThickness paintOrder panose1 pathLength
-patternContentUnits patternTransform patternUnits pointerEvents points
-pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits
-r radius refX refY renderingIntent repeatCount repeatDur requiredExtensions
-requiredFeatures restart result rotate rx ry scale seed shapeRendering slope
-spacing specularConstant specularExponent speed spreadMethod startOffset
-stdDeviation stemh stemv stitchTiles stopColor stopOpacity
-strikethroughPosition strikethroughThickness string stroke strokeDasharray
-strokeDashoffset strokeLinecap strokeLinejoin strokeMiterlimit strokeOpacity
-strokeWidth surfaceScale systemLanguage tableValues targetX targetY textAnchor
-textDecoration textLength textRendering to transform u1 u2 underlinePosition
-underlineThickness unicode unicodeBidi unicodeRange unitsPerEm vAlphabetic
-vHanging vIdeographic vMathematical values vectorEffect version vertAdvY
-vertOriginX vertOriginY viewBox viewTarget visibility widths wordSpacing
-writingMode x x1 x2 xChannelSelector xHeight xlinkActuate xlinkArcrole
-xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace
-y y1 y2 yChannelSelector z zoomAndPan
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/test-utils-it-IT.html b/docs/test-utils-it-IT.html deleted file mode 100644 index d76d5c91a4..0000000000 --- a/docs/test-utils-it-IT.html +++ /dev/null @@ -1,624 +0,0 @@ - - - - - - - Utilità di Test | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Utilità di Test -

-
- -

React.addons.TestUtils semplifica la validazione dei componenti React nel framework di test di tua scelta (noi utilizziamo Jest).

-

Simulate #

Simulate.{eventName}(
-  DOMElement element,
-  [object eventData]
-)
-
-

Simula l'inoltro di un evento su un nodo DOM con dei dati dell'evento opzionali eventData. Questa è probabilmente l'utilità più essenziale in ReactTestUtils.

- -

Cliccare un elemento

-
var node = ReactDOM.findDOMNode(this.refs.button);
-React.addons.TestUtils.Simulate.click(node);
-
-

Cambiare il valore di un campo di input e in seguito premere INVIO

-
var node = ReactDOM.findDOMNode(this.refs.input);
-node.value = 'giraffe';
-React.addons.TestUtils.Simulate.change(node);
-React.addons.TestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
-
-

nota che dovrai fornire tu stesso ciascuna proprietà dell'evento utilizzata nel tuo componente (ad es. keyCode, which, etc...) in quanto React non crea alcuna di esse per te

- -

Simulate possiede un metodo per ciascun evento che React comprende.

-

renderIntoDocument #

ReactComponent renderIntoDocument(
-  ReactElement instance
-)
-
-

Effettua il rendering di un componente in un nodo DOM staccato dal documento. Questa funzione richiede la presenza del DOM.

-

mockComponent #

object mockComponent(
-  function componentClass,
-  [string mockTagName]
-)
-
-

Passa il mock di un componente a questo metodo per aumentarlo con metodi utili che gli permettono di essere utilizzato come un componente React fantoccio. Anziché essere visualizzato come al solito, il componente diventerà un semplice <div> (o qualsiasi altro tag se fornito come valore di mockTagName) contenente ciascun figlio fornito.

-

isElement #

boolean isElement(
-  ReactElement element
-)
-
-

Restituisce true se element è un qualunque ReactElement.

-

isElementOfType #

boolean isElementOfType(
-  ReactElement element,
-  function componentClass
-)
-
-

Restituisce true se element è un ReactElement il cui tipo è la classe React componentClass.

-

isDOMComponent #

boolean isDOMComponent(
-  ReactComponent instance
-)
-
-

Restituisce true se instance è un componente DOM (come ad esempio <div> o <span>).

-

isCompositeComponent #

boolean isCompositeComponent(
-  ReactComponent instance
-)
-
-

Restituisce true se instance è un componente composito (creato tramite React.createClass()).

-

isCompositeComponentWithType #

boolean isCompositeComponentWithType(
-  ReactComponent instance,
-  function componentClass
-)
-
-

Restituisce true se instance è un componente composito (creato tramite React.createClass()) il cui tipo è una classe React dal nome componentClass.

-

findAllInRenderedTree #

array findAllInRenderedTree(
-  ReactComponent tree,
-  function test
-)
-
-

Attraversa tutti i componenti in tree e accumula tutti i componenti per i quali test(component) è true. Non è molto utile usata da sola, ma diventa ptente se usata come primitiva per altre utilità di test.

-

scryRenderedDOMComponentsWithClass #

array scryRenderedDOMComponentsWithClass(
-  ReactComponent tree, string className
-)
-
-

Trova tutte le istanze di componenti nell'albero visualizzato che sono componenti DOM il cui nome di classe corrisponde a className.

-

findRenderedDOMComponentWithClass #

ReactComponent findRenderedDOMComponentWithClass(
-  ReactComponent tree,
-  string className
-)
-
-

Simile a scryRenderedDOMComponentsWithClass() ma si aspetta di trovare un solo risultato, e restituisce quel solo risultato, oppure lancia un'eccezione se viene trovato qualunque altro numero di occorrenze diverso da uno.

-

scryRenderedDOMComponentsWithTag #

array scryRenderedDOMComponentsWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

Trova tutte le istanze di componenti nell'albero visualizzato che sono componenti DOM il cui nome di tag corrisponde a tagName.

-

findRenderedDOMComponentWithTag #

ReactComponent findRenderedDOMComponentWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

Simile a scryRenderedDOMComponentsWithTag() ma si aspetta di trovare un solo risultato, e restituisce quel solo risultato, oppure lancia un'eccezione se viene trovato qualunque altro numero di occorrenze diverso da uno.

-

scryRenderedComponentsWithType #

array scryRenderedComponentsWithType(
-  ReactComponent tree,
-  function componentClass
-)
-
-

Trova tutte le istanze di componenti il cui tipo corrisponde a componentClass.

-

findRenderedComponentWithType #

ReactComponent findRenderedComponentWithType(
-  ReactComponent tree, function componentClass
-)
-
-

Simile a scryRenderedComponentsWithType() si aspetta di trovare un solo risultato, oppure lancia un'eccezione se viene trovato qualunque altro numero di occorrenze diverso da uno.

-

Rendering superficiale #

-

Il rendering superficiale è una caratteristica sperimentale che ti permette di effettuare il rendering di un componente "ad un livello di profondità" e asserire dei fatti su ciò che viene restituito dal suo metodo render, senza preoccuparti del comportamento dei componenti figli, i quali non sono né istanziati né viene effettuato il rendering. Questo non richiede la presenza di un DOM.

-
ReactShallowRenderer createRenderer()
-
-

Chiama questo metodo nei tuoi test per creare un renderer superficiale. Puoi pensare ad esso come un "luogo" in cui effettuare il rendering del componente che stai validando, dove può rispondere ad eventi e aggiornarsi.

-
shallowRenderer.render(
-  ReactElement element
-)
-
-

Simile a ReactDOM.render.

-
ReactComponent shallowRenderer.getRenderOutput()
-
-

Dopo che render è stato chiamato, restituisce un output di cui è stato effettuato un rendering superficiale. Puoi quindi iniziare ad asserire fatti sull'output. Ad esempio, se il metodo render del tuo componente resituisce:

-
<div>
-  <span className="heading">Titolo</span>
-  <Subcomponent foo="bar" />
-</div>
-
-

Allora puoi asserire:

-
result = renderer.getRenderOutput();
-expect(result.type).toBe('div');
-expect(result.props.children).toEqual([
-  <span className="heading">Titolo</span>,
-  <Subcomponent foo="bar" />
-]);
-
-

La validazione superficiale ha al momento alcune limitazioni, in particolare non supporta i riferimenti. Stiamo rilasciando questa caratteristica in anticipo e gradiremmo ascoltare il parere della comunità React per la direzione in cui debba evolvere.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/test-utils-ja-JP.html b/docs/test-utils-ja-JP.html deleted file mode 100644 index 7feaacf107..0000000000 --- a/docs/test-utils-ja-JP.html +++ /dev/null @@ -1,577 +0,0 @@ - - - - - - - テストユーティリティ | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- テストユーティリティ -

-
- -

React.addons.TestUtils は選んだテストフレームワーク(私たちはJestを使っています)において、Reactのコンポーネントをテストすることを簡単にします。

-

Simulate #

Simulate.{eventName}(DOMElement element, object eventData)
-
-

オプションの eventData であるイベントデータと共に、DOMノードの上でイベントのディスパッチをシミュレートします。 これは ReactTestUtils の中で最も有用なユーティリティでしょう。

- -

使用例:

-
var node = ReactDOM.findDOMNode(this.refs.input);
-React.addons.TestUtils.Simulate.click(node);
-React.addons.TestUtils.Simulate.change(node, {target: {value: 'Hello, world'}});
-React.addons.TestUtils.Simulate.keyDown(node, {key: "Enter"});
-
-

Simulate はReactが理解出来る全てのイベントのためのメソッドを持っています。

-

renderIntoDocument #

ReactComponent renderIntoDocument(ReactElement instance)
-
-

コンポーネントをドキュメントの中で分離したDOMノードにレンダリングします。 この関数はDOMを必要とします。

-

mockComponent #

object mockComponent(function componentClass, string? mockTagName)
-
-

有効なダミーのReactのコンポーネントとして使われることを許可するメソッドと共にこれを増強させるためにモックとなったコンポーネントモジュールをこのメソッドに渡してください。いつものようにレンダリングされる代わりに、コンポーネントは単純で、提供された子要素はどんなものでも含む <div>mockTagName が提供されている場合はそのタグ)になるでしょう。

-

isElement #

boolean isElement(ReactElement element)
-
-

element が何かしらのReactElementだった場合に true を返します。

-

isElementOfType #

boolean isElementOfType(ReactElement element, function componentClass)
-
-

element がReactの componentClass 型であるReactElementだった場合に true を返します。

-

isDOMComponent #

boolean isDOMComponent(ReactComponent instance)
-
-

instance がDOMのコンポーネントだった場合に true を返します( <div><span> のように)。

-

isCompositeComponent #

boolean isCompositeComponent(ReactComponent instance)`
-
-

instance が複合的なコンポーネントだった場合に true を返します(React.createClass() で作成されるような)。

-

isCompositeComponentWithType #

boolean isCompositeComponentWithType(ReactComponent instance, function componentClass)
-
-

instance が複合的なコンポーネントだった場合に true を返します(React.createClass() で作成され、型がReactの componentClass であるような)。

-

findAllInRenderedTree #

array findAllInRenderedTree(ReactComponent tree, function test)
-
-

tree の中の全てのコンポーネントや test(component)true となる蓄積された全てのコンポーネントを検討します。これはこれだけでは有用ではありませんが、他のテストユーティリティの根本として使われます。

-

scryRenderedDOMComponentsWithClass #

array scryRenderedDOMComponentsWithClass(ReactComponent tree, string className)
-
-

レンダリングされたツリーの中で、DOMコンポーネントであり、クラス名が className にマッチする、コンポーネントの全てのインスタンスを見つけます。

-

findRenderedDOMComponentWithClass #

ReactComponent findRenderedDOMComponentWithClass(ReactComponent tree, string className)
-
-

scryRenderedDOMComponentsWithClass() に似ていますが、結果が1つであること、それを返すこと、またはマッチする個数が1個以外だった場合に例外を投げることを予期します。

-

scryRenderedDOMComponentsWithTag #

array scryRenderedDOMComponentsWithTag(ReactComponent tree, string tagName)
-
-

レンダリングされたツリーの中で、DOMコンポーネントであり、タグ名が tagName にマッチする、コンポーネントの全てのインスタンスを見つけます。

-

findRenderedDOMComponentWithTag #

ReactComponent findRenderedDOMComponentWithTag(ReactComponent tree, string tagName)
-
-

scryRenderedDOMComponentsWithTag() に似ていますが、結果が1つであること、それを返すこと、またはマッチする個数が1個以外だった場合に例外を投げることを予期します。

-

scryRenderedComponentsWithType #

array scryRenderedComponentsWithType(ReactComponent tree, function componentClass)
-
-

型名が componentClass と同様である、コンポーネントの全てのインスタンスを見つけます。

-

findRenderedComponentWithType #

ReactComponent findRenderedComponentWithType(ReactComponent tree, function componentClass)
-
-

scryRenderedComponentsWithType() と同じですが、結果が1つであること、それを返すこと、またはマッチする個数が1個以外だった場合に例外を投げることを予期します。

-

Shallow rendering #

-

シャローレンダリングは"第一段階の深さ"であるコンポーネントをレンダリングすることを強制し、レンダリングメソッドが返すものについての事実をアサートし、インスタンスを生成したり、レンダリングされたりしない子のコンポーネントの振る舞いについては関心しない実験的な特徴です。これはDOMを必要としません。

-
ReactShallowRenderer createRenderer()
-
-

シャローレンダラーを作成するにはこれをテストの中で呼んでください。これをあなたがテストするコンポーネントをレンダリングする場所であると考えることができます。この場所はイベントに返答したり、これ自身を更新したりできます。

-
shallowRenderer.render(ReactElement element)
-
-

ReactDOM.render に同様。

-
ReactComponent shallowRenderer.getRenderOutput()
-
-

render が呼ばれた後、浅くレンダリングされた出力を返します。その後、その出力に関しての事実をアサートすることができます。例えば、以下のように、コンポーネントのレンダリングメソッドが返してきた場合は、

-
<div>
-  <span className="heading">Title</span>
-  <Subcomponent foo="bar" />
-</div>
-
-

以下のように、アサートできます。

-
result = renderer.getRenderOutput();
-expect(result.type).toBe('div');
-expect(result.props.children).toEqual([
-  <span className="heading">Title</span>,
-  <Subcomponent foo="bar" />
-]);
-
-

シャローテスティングは現在、制限があります。はっきり言うと、参照をサポートしていません。私たちは、この特徴を早めにリリースし、これが、どのように進化していくか、Reactのコミュニティのフィードバックを評価するつもりです。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/test-utils-ko-KR.html b/docs/test-utils-ko-KR.html deleted file mode 100644 index f768e3dcbd..0000000000 --- a/docs/test-utils-ko-KR.html +++ /dev/null @@ -1,628 +0,0 @@ - - - - - - - 테스트 유틸리티 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 테스트 유틸리티 -

-
- -

ReactTestUtils는 선택한 테스트 프레임워크(React는 Jest를 사용)에서 React 컴포넌트를 테스트하기 쉽게 합니다.

-
var ReactTestUtils = require('react-addons-test-utils');
-

Simulate #

Simulate.{eventName}(
-  DOMElement element,
-  [object eventData]
-)
-
-

DOM 노드에 이벤트 디스패치하는 것을 시뮬레이트합니다. 선택적으로 eventData를 통해 이벤트 데이터도 처리할 수 있습니다. 아마 ReactTestUtils에서 가장 유용한 유틸리티일 것 입니다.

- -

엘리먼트 클릭

-
// <button ref="button">...</button>
-var node = this.refs.button;
-ReactTestUtils.Simulate.click(node);
-
-

입력 필드의 값을 변경하고 엔터 누르기.

-
// <input ref="input" />
-var node = this.refs.input;
-node.value = 'giraffe';
-ReactTestUtils.Simulate.change(node);
-ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
-
-

컴포넌트에서 사용할 이벤트 프로퍼티(예를 들어 keyCode, which, 등등...)는 React에서 만들어 주지 않으므로 직접 제공해야 합니다.

- -

Simulate에는 React가 이해하는 모든 이벤트에 대해 메소드가 있습니다.

-

renderIntoDocument #

ReactComponent renderIntoDocument(
-  ReactElement instance
-)
-
-

문서의 detach된 DOM 노드에 컴포넌트를 렌더합니다. 이 기능은 DOM을 필요로 합니다.

- -
-

주의:

- -

React를 임포트하기 전에 window, window.document, window.document.createElement을 전역적으로 사용가능하게 해두어야 합니다. 아니면 React는 DOM과 setState같은 메소드가 동작하지 않는다고 생각할 수 있습니다.

-
-

mockComponent #

object mockComponent(
-  function componentClass,
-  [string mockTagName]
-)
-
-

목 컴포넌트 모듈을 이 메소드에 넘겨 더미 React 컴포넌트로 사용할 수 있도록 합니다. 이 더미는 유용한 메소드와 함께 사용해 기능을 보강할 수 있습니다. 일반적인 렌더링과는 다르게, 컴포넌트는 제공된 자식을 포함하는 평범한 <div>가 됩니다. (mockTagName을 통해 div가 아닌 다른 태그를 지정해 줄 수도 있습니다.)

-

isElement #

boolean isElement(
-  ReactElement element
-)
-
-

element가 ReactElement면 true를 리턴합니다.

-

isElementOfType #

boolean isElementOfType(
-  ReactElement element,
-  function componentClass
-)
-
-

element가 React componentClass 타입인 ReactElement면 true를 리턴합니다.

-

isDOMComponent #

boolean isDOMComponent(
-  ReactComponent instance
-)
-
-

instance가 (<div><span>같은) DOM 컴포넌트면 true를 리턴합니다.

-

isCompositeComponent #

boolean isCompositeComponent(ReactComponent instance)`
-
-

instance가 (React.createClass()로 생성된) 복합 컴포넌트면 true를 리턴합니다.

-

isCompositeComponentWithType #

boolean isCompositeComponentWithType(
-  ReactComponent instance,
-  function componentClass
-)
-
-

instance가 (React.createClass()로 생성된) 복합 컴포넌트고 React componentClass 타입이면 true를 리턴합니다.

-

findAllInRenderedTree #

array findAllInRenderedTree(
-  ReactComponent tree,
-  function test
-)
-
-

tree안의 모든 컴포넌트에서 test(component)true인 모든 컴포넌트를 모읍니다. 이것만으로는 그렇게 유용하지 않습니다만, 다른 테스트 유틸와 같이 사용합니다.

-

scryRenderedDOMComponentsWithClass #

array scryRenderedDOMComponentsWithClass(
-  ReactComponent tree, string className
-)
-
-

렌더된 트리의 모든 컴포넌트 인스턴스 중에서 클래스 이름이 className인 DOM 컴포넌트들을 찾습니다.

-

findRenderedDOMComponentWithClass #

ReactComponent findRenderedDOMComponentWithClass(ReactComponent tree, string className)
-
-

scryRenderedDOMComponentsWithClass()와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.

-

scryRenderedDOMComponentsWithTag #

array scryRenderedDOMComponentsWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

렌더된 트리의 모든 컴포넌트 인스턴스중에서 태그 이름이 tagName인 DOM 컴포넌트들을 찾습니다.

-

findRenderedDOMComponentWithTag #

ReactComponent findRenderedDOMComponentWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

scryRenderedDOMComponentsWithTag()와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.

-

scryRenderedComponentsWithType #

array scryRenderedComponentsWithType(
-  ReactComponent tree,
-  function componentClass
-)
-
-

타입이 componentClass인 모든 컴포넌트 인스턴스를 찾습니다.

-

findRenderedComponentWithType #

ReactComponent findRenderedComponentWithType(
-  ReactComponent tree, function componentClass
-)
-
-

scryRenderedComponentsWithType()와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.

-

얕은 렌더링 #

-

얕은 렌더링은 "한 단계 깊이의" 컴포넌트를 렌더할 수 있는 실험적인 기능입니다. 자식 컴포넌트가 인스턴스화 되거나 렌더되는 등의 동작에 대한 걱정 없이 렌더 메소드가 반환하는 것만 검증합니다. 이 기능은 DOM이 필요하지 않습니다.

-
ReactShallowRenderer createRenderer()
-
-

테스트에서 얕은 렌더러를 생성하고자 할때 호출합니다. 이를 이벤트와 업데이트에 스스로 반응하는 컴포넌트를 렌더하기 위한 "장소"라고 생각할 수 있습니다.

-
shallowRenderer.render(
-  ReactElement element
-)
-
-

ReactDOM.render와 유사합니다.

-
ReactElement shallowRenderer.getRenderOutput()
-
-

render가 호출 된 후, 얕게 렌더된 결과물을 반환합니다. 그 후엔 결과물에 대한 검증을 시작할 수 있습니다. 예를 들어 컴포넌트의 렌더 메소드가 다음을 반환한다면:

-
<div>
-  <span className="heading">Title</span>
-  <Subcomponent foo="bar" />
-</div>
-
-

그 후에는 검증할 수 있습니다:

-
result = renderer.getRenderOutput();
-expect(result.type).toBe('div');
-expect(result.props.children).toEqual([
-  <span className="heading">Title</span>,
-  <Subcomponent foo="bar" />
-]);
-
-

현재 얕은 테스트는 refs를 지원하지 않는 등 몇가지 제약사항이 있습니다. 우리는 이 기능을 빠르게 먼저 배포하고 React 커뮤니티의 피드백을 받아 나아갈 방향을 찾고자 합니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/test-utils-zh-CN.html b/docs/test-utils-zh-CN.html deleted file mode 100644 index 8ec4e7075d..0000000000 --- a/docs/test-utils-zh-CN.html +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - - 测试工具 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 测试工具 -

-
- -

ReactTestUtils 使你在你选择的测试框架中 (我们使用 Jest) 测试 React 组件变得容易。

-
var ReactTestUtils = require('react-addons-test-utils');
-

Simulate #

Simulate.{eventName}(
-  DOMElement element,
-  [object eventData]
-)
-
-

模拟一个在 DOM 节点上带有可选 eventData 事件数据的事件派遣(event dispatch)。这可能是 ReactTestUtils 里单独最有用的工具。

- -

点击一个元素

-
// <button ref="button">...</button>
-var node = this.refs.button;
-ReactTestUtils.Simulate.click(node);
-
-

改变 input 域的值然后点击 回车。

-
// <input ref="input" />
-var node = this.refs.input;
-node.value = 'giraffe';
-ReactTestUtils.Simulate.change(node);
-ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
-
-

注意你将必须提供任何你在你的组件里使用的事件属性(例如 keyCode, which, 等等)因为React没有为你创建任何这类东西。

- -

Simulate has a method for every event that React understands.

-

renderIntoDocument #

ReactComponent renderIntoDocument(
-  ReactElement instance
-)
-
-

渲染一个组件到 document 里的 detached DOM 节点。这个函数需要一个 DOM。

- -
-

注意:

- -

在你 import React 之前,你需要让 window, window.documentwindow.document.createElement 全局可用。 -不然 React 会认为它不能访问 DOM 然后类似 setState 的方法会不工作。

-
-

mockComponent #

object mockComponent(
-  function componentClass,
-  [string mockTagName]
-)
-
-

传入一个 mocked 组件模块到这个方法来给它增加有用的方法,使它可以被用作 dummy React 组件。代替像通常一样的渲染,组件会成为一个简单的包含了任意被提供的子级的 <div> (或者其他 tag 名,如果提供了 mockTagName

-

isElement #

boolean isElement(
-  ReactElement element
-)
-
-

返回 true 如果 element 是任意的 ReactElement。

-

isElementOfType #

boolean isElementOfType(
-  ReactElement element,
-  function componentClass
-)
-
-

返回 true 如果 element 是一个类型是 React componentClass 的 ReactElement。

-

isDOMComponent #

boolean isDOMComponent(
-  ReactComponent instance
-)
-
-

返回 true 如果 instance 是一个 DOM 组件 (比如一个 <div> 或者 <span>)。

-

isCompositeComponent #

boolean isCompositeComponent(
-  ReactComponent instance
-)
-
-

返回 true 如果 instance 是一个复合组件 (由 React.createClass() 创建)。

-

isCompositeComponentWithType #

boolean isCompositeComponentWithType(
-  ReactComponent instance,
-  function componentClass
-)
-
-

返回 true 如果 instance 是一个类型为 React componentClass 的复合组件 (由 React.createClass() 创建)。

-

findAllInRenderedTree #

array findAllInRenderedTree(
-  ReactComponent tree,
-  function test
-)
-
-

遍历 tree 里所有的组件,并累积所有 test(component)true 的组件。它本身并没有什么用,但是它被用作其他测试工具的基本元素。

-

scryRenderedDOMComponentsWithClass #

array scryRenderedDOMComponentsWithClass(
-  ReactComponent tree, string className
-)
-
-

在渲染的树中查找所有 DOM组件的类名匹配className 的组件实例。

-

findRenderedDOMComponentWithClass #

ReactComponent findRenderedDOMComponentWithClass(
-  ReactComponent tree,
-  string className
-)
-
-

类似 scryRenderedDOMComponentsWithClass() 除了只有一个返回结果,并且要么返回这个结果,要么如果还有其他的匹配项就抛出一个异常。

-

scryRenderedDOMComponentsWithTag #

array scryRenderedDOMComponentsWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

在渲染的树中查找所有 DOM 组件的 tag 名匹配 tagName 的组件实例。

-

findRenderedDOMComponentWithTag #

ReactComponent findRenderedDOMComponentWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

类似 scryRenderedDOMComponentsWithTag() 除了只有一个返回结果,并且要么返回这个结果,要么如果还有其他的匹配项就抛出一个异常。

-

scryRenderedComponentsWithType #

array scryRenderedComponentsWithType(
-  ReactComponent tree,
-  function componentClass
-)
-
-

查找所有类型等于 componentClass 的组件实例。

-

findRenderedComponentWithType #

ReactComponent findRenderedComponentWithType(
-  ReactComponent tree, function componentClass
-)
-
-

类似 scryRenderedComponentsWithType() 除了只有一个返回结果,并且要么返回这个结果,要么如果还有其他的匹配项就抛出一个异常。

-

Shallow rendering(浅渲染) #

-

浅渲染是一个实验性特性,让你渲染一个组件为 "one level deep" 并且断言渲染方法返回的内容,不用担心子组件的行为,它们没有被实例化或者渲染。这个方式不需要一个 DOM。

-
ReactShallowRenderer createRenderer()
-
-

在你的测试里调用它来创建一个浅渲染器。你可以把它想做是一个你渲染你要测试的组件的 "地方",它可以自己响应事件并更新。

-
shallowRenderer.render(
-  ReactElement element
-)
-
-

类似于 ReactDOM.render

-
ReactElement shallowRenderer.getRenderOutput()
-
-

render 被调用后,返回一个浅渲染的输出。你可以接着断言输出的内容。例如,如果你的组件的渲染方法返回:

-
<div>
-  <span className="heading">Title</span>
-  <Subcomponent foo="bar" />
-</div>
-
-

然后你可以断言:

-
var renderer = ReactTestUtils.createRenderer();
-result = renderer.getRenderOutput();
-expect(result.type).toBe('div');
-expect(result.props.children).toEqual([
-  <span className="heading">Title</span>,
-  <Subcomponent foo="bar" />
-]);
-
-

浅测试现在有一些限制,即不支持 refs。我们在早期发布这个特性,并感激 React 社区关于它应该如何演化的反馈。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/test-utils.html b/docs/test-utils.html index 50a4710c25..10d21827ae 100644 --- a/docs/test-utils.html +++ b/docs/test-utils.html @@ -1,12 +1,14 @@ + + - Test Utilities | React - - + Test Utilities - React + + @@ -44,31 +46,262 @@
-
+
+ Edit on GitHub +

+ Test Utilities +

+
+ +

Importing

+
import ReactTestUtils from 'react-addons-test-utils' // ES6
+var ReactTestUtils = require('react-addons-test-utils') // ES5 with npm
+var ReactTestUtils = React.addons.TestUtils; // ES5 with react-with-addons.js
+

Overview #

+

ReactTestUtils makes it easy to test React components in the testing framework of your choice. At Facebook we use Jest for painless JavaScript testing. Learn how to get started with Jest through the Jest website's React Tutorial.

+ +
+

Note:

+ +

Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components' output. If you're deciding on a unit testing utility to use together with Jest, or any other test runner, it's worth checking out: http://airbnb.io/enzyme/

+
+ + +

Shallow Rendering #

+

Shallow rendering lets you render a component "one level deep" and assert facts about what its render method returns, without worrying about the behavior of child components, which are not instantiated or rendered. This does not require a DOM.

+ + + +

Call createRenderer() in your tests to create a shallow renderer. You can think of this as a "place" to render the component you're testing, and from which you can extract the component's output.

+ +

shadowRenderer.render() is similar to ReactDOM.render() but it doesn't require DOM and only renders a single level deep. This means you can test components in isolated from how their children are implemented.

+ +

After shadowRenderer.render() has been called, you can use shallowRenderer.getRenderOutput() to get the shallowly rendered output.

+ +

You can then begin to assert facts about the output. For example, if your component's render method returns:

+
<div>
+  <span className="heading">Title</span>
+  <Subcomponent foo="bar" />
+</div>
+
+

Then you can assert:

+
var renderer = ReactTestUtils.createRenderer();
+result = renderer.getRenderOutput();
+expect(result.type).toBe('div');
+expect(result.props.children).toEqual([
+  <span className="heading">Title</span>,
+  <Subcomponent foo="bar" />
+]);
+
+

Shallow testing currently has some limitations, namely not supporting refs.

+ +

We also recommend checking out Enzyme's Shallow Rendering API. It provides a nicer higher-level API over the same functionality.

+ +
+

Reference #

Simulate #

Simulate.{eventName}(
+  element,
+  [eventData]
+)
+
+

Simulate an event dispatch on a DOM node with optional eventData event data.

+ +

Simulate has a method for every event that React understands.

+ +

Clicking an element

+
// <button ref="button">...</button>
+var node = this.refs.button;
+ReactTestUtils.Simulate.click(node);
+
+

Changing the value of an input field and then pressing ENTER.

+
// <input ref="input" />
+var node = this.refs.input;
+node.value = 'giraffe';
+ReactTestUtils.Simulate.change(node);
+ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
+
+
+

Note

+ +

You will have to provide any event property that you're using in your component (e.g. keyCode, which, etc...) as React is not creating any of these for you.

+
+ +
+

renderIntoDocument() #

renderIntoDocument(instance)
+
+

Render a component into a detached DOM node in the document. This function requires a DOM.

+ +
+

Note:

+ +

You will need to have window, window.document and window.document.createElement globally available before you import React. Otherwise React will think it can't access the DOM and methods like setState won't work.

+
+ +
+

mockComponent() #

mockComponent(
+  componentClass,
+  [mockTagName]
+)
+
+

Pass a mocked component module to this method to augment it with useful methods that allow it to be used as a dummy React component. Instead of rendering as usual, the component will become a simple <div> (or other tag if mockTagName is provided) containing any provided children.

+ +
+

isElement() #

isElement(element)
+
+

Returns true if element is any React element.

+ +
+

isElementOfType() #

isElementOfType(
+  element,
+  componentClass
+)
+
+

Returns true if element is a React element whose type is of a React componentClass.

+ +
+

isDOMComponent() #

isDOMComponent(instance)
+
+

Returns true if instance is a DOM component (such as a <div> or <span>).

+ +
+

isCompositeComponent() #

isCompositeComponent(instance)
+
+

Returns true if instance is a user-defined component, such as a class or a function.

+ +
+

isCompositeComponentWithType() #

isCompositeComponentWithType(
+  instance,
+  componentClass
+)
+
+

Returns true if instance is a component whose type is of a React componentClass.

+ +
+

findAllInRenderedTree() #

findAllInRenderedTree(
+  tree,
+  test
+)
+
+

Traverse all components in tree and accumulate all components where test(component) is true. This is not that useful on its own, but it's used as a primitive for other test utils.

+ +
+

scryRenderedDOMComponentsWithClass() #

scryRenderedDOMComponentsWithClass(
+  tree,
+  className
+)
+
+

Finds all DOM elements of components in the rendered tree that are DOM components with the class name matching className.

+ +
+

findRenderedDOMComponentWithClass() #

findRenderedDOMComponentWithClass(
+  tree,
+  className
+)
+
+

Like scryRenderedDOMComponentsWithClass() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.

+ +
+

scryRenderedDOMComponentsWithTag() #

scryRenderedDOMComponentsWithTag(
+  tree,
+  tagName
+)
+
+

Finds all DOM elements of components in the rendered tree that are DOM components with the tag name matching tagName.

+ +
+

findRenderedDOMComponentWithTag() #

findRenderedDOMComponentWithTag(
+  tree,
+  tagName
+)
+
+

Like scryRenderedDOMComponentsWithTag() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.

+ +
+

scryRenderedComponentsWithType() #

scryRenderedComponentsWithType(
+  tree,
+  componentClass
+)
+
+

Finds all instances of components with type equal to componentClass.

+ +
+

findRenderedComponentWithType() #

findRenderedComponentWithType(
+  tree,
+  componentClass
+)
+
+

Same as scryRenderedComponentsWithType() but expects there to be one result and returns that one result, or throws exception if there is any other number of matches besides one.

+ +
+

Shallow Rendering #

createRenderer() #

createRenderer()
+
+

Call this in your tests to create a shallow renderer.

+ +
+

shallowRenderer.render() #

shallowRenderer.render(
+  element
+)
+
+

Similar to ReactDOM.render but it doesn't require DOM and only renders a single level deep. See Shallow Rendering.

+ +
+

shallowRenderer.getRenderOutput() #

shallowRenderer.getRenderOutput()
+
+

After shallowRenderer.render() has been called, returns shallowly rendered output.

+ + +
+ + ← Prev + + +
+
+ - - - - + + + + - - - - - - - @@ -433,188 +536,57 @@
+ - -
- Edit on GitHub -

- Test Utilities -

-
- -

ReactTestUtils makes it easy to test React components in the testing framework of your choice. At Facebook we use Jest for painless JavaScript testing. Learn how to get started with Jest through the Jest website's React Tutorial.

-
var ReactTestUtils = require('react-addons-test-utils');
-
-
-

Note:

- -

Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components' output. If you're deciding on a unit testing utility to use together with Jest, or any other test runner, it's worth checking out: http://airbnb.io/enzyme/

-
-

Simulate #

Simulate.{eventName}(
-  DOMElement element,
-  [object eventData]
-)
-
-

Simulate an event dispatch on a DOM node with optional eventData event data. This is possibly the single most useful utility in ReactTestUtils.

- -

Clicking an element

-
// <button ref="button">...</button>
-var node = this.refs.button;
-ReactTestUtils.Simulate.click(node);
-
-

Changing the value of an input field and then pressing ENTER.

-
// <input ref="input" />
-var node = this.refs.input;
-node.value = 'giraffe';
-ReactTestUtils.Simulate.change(node);
-ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
-
-

Note that you will have to provide any event property that you're using in your component (e.g. keyCode, which, etc...) as React is not creating any of these for you.

- -

Simulate has a method for every event that React understands.

-

renderIntoDocument #

ReactComponent renderIntoDocument(
-  ReactElement instance
-)
-
-

Render a component into a detached DOM node in the document. This function requires a DOM.

- -
-

Note:

- -

You will need to have window, window.document and window.document.createElement - globally available before you import React. Otherwise React will think it can't access the DOM and methods like setState won't work.

-
-

mockComponent #

object mockComponent(
-  function componentClass,
-  [string mockTagName]
-)
-
-

Pass a mocked component module to this method to augment it with useful methods that allow it to be used as a dummy React component. Instead of rendering as usual, the component will become a simple <div> (or other tag if mockTagName is provided) containing any provided children.

-

isElement #

boolean isElement(
-  ReactElement element
-)
-
-

Returns true if element is any ReactElement.

-

isElementOfType #

boolean isElementOfType(
-  ReactElement element,
-  function componentClass
-)
-
-

Returns true if element is a ReactElement whose type is of a React componentClass.

-

isDOMComponent #

boolean isDOMComponent(
-  ReactComponent instance
-)
-
-

Returns true if instance is a DOM component (such as a <div> or <span>).

-

isCompositeComponent #

boolean isCompositeComponent(
-  ReactComponent instance
-)
-
-

Returns true if instance is a composite component (created with React.createClass()).

-

isCompositeComponentWithType #

boolean isCompositeComponentWithType(
-  ReactComponent instance,
-  function componentClass
-)
-
-

Returns true if instance is a composite component (created with React.createClass()) whose type is of a React componentClass.

-

findAllInRenderedTree #

array findAllInRenderedTree(
-  ReactComponent tree,
-  function test
-)
-
-

Traverse all components in tree and accumulate all components where test(component) is true. This is not that useful on its own, but it's used as a primitive for other test utils.

-

scryRenderedDOMComponentsWithClass #

array scryRenderedDOMComponentsWithClass(
-  ReactComponent tree, 
-  string className
-)
-
-

Finds all DOM elements of components in the rendered tree that are DOM components with the class name matching className.

-

findRenderedDOMComponentWithClass #

DOMElement findRenderedDOMComponentWithClass(
-  ReactComponent tree,
-  string className
-)
-
-

Like scryRenderedDOMComponentsWithClass() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.

-

scryRenderedDOMComponentsWithTag #

array scryRenderedDOMComponentsWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

Finds all DOM elements of components in the rendered tree that are DOM components with the tag name matching tagName.

-

findRenderedDOMComponentWithTag #

DOMElement findRenderedDOMComponentWithTag(
-  ReactComponent tree,
-  string tagName
-)
-
-

Like scryRenderedDOMComponentsWithTag() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.

-

scryRenderedComponentsWithType #

array scryRenderedComponentsWithType(
-  ReactComponent tree,
-  function componentClass
-)
-
-

Finds all instances of components with type equal to componentClass.

-

findRenderedComponentWithType #

ReactComponent findRenderedComponentWithType(
-  ReactComponent tree, 
-  function componentClass
-)
-
-

Same as scryRenderedComponentsWithType() but expects there to be one result and returns that one result, or throws exception if there is any other number of matches besides one.

-

Shallow rendering #

-

Shallow rendering is an experimental feature that lets you render a component "one level deep" and assert facts about what its render method returns, without worrying about the behavior of child components, which are not instantiated or rendered. This does not require a DOM.

-
ReactShallowRenderer createRenderer()
-
-

Call this in your tests to create a shallow renderer. You can think of this as a "place" to render the component you're testing, where it can respond to events and update itself.

-
shallowRenderer.render(
-  ReactElement element
-)
-
-

Similar to ReactDOM.render.

-
ReactElement shallowRenderer.getRenderOutput()
-
-

After render has been called, returns shallowly rendered output. You can then begin to assert facts about the output. For example, if your component's render method returns:

-
<div>
-  <span className="heading">Title</span>
-  <Subcomponent foo="bar" />
-</div>
-
-

Then you can assert:

-
var renderer = ReactTestUtils.createRenderer();
-result = renderer.getRenderOutput();
-expect(result.type).toBe('div');
-expect(result.props.children).toEqual([
-  <span className="heading">Title</span>,
-  <Subcomponent foo="bar" />
-]);
-
-

Shallow testing currently has some limitations, namely not supporting refs. We're releasing this feature early and would appreciate the React community's feedback on how it should evolve.

- - -
- - ← Prev - - - Next → - -
-
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
- -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Pensare in React -

-
- -

di Pete Hunt

- -

React è, a mio parere, la maniera più adeguata di costruire veloci applicazioni Web di grandi dimensioni con JavaScript. Ha scalato molto bene per noi a Facebook e Instagram.

- -

Una delle molte parti migliori di React è come ti fa pensare alle applicazioni mentre le costruisci. In questo articolo vi guiderò attraverso il processo di pensiero per la costruzione di una tabella di dati di prodotti che possono essere cercati usando React.

-

Comincia con un mock #

-

Immagina di possedere già una API JSON e un mock prodotto dai nostri designer. I nostri designer apparentemente non sono molto capaci perché il mock ha questo aspetto:

- -

Mockup

- -

La nostra API JSON restituisce dei dati che somigliano a quanto segue:

-
[
-  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
-  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
-  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
-  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
-  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
-  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
-];
-

Passo 1: suddividi la UI in una gerarchia di componenti #

-

La prima azione che vorrai compiere è disegnare dei rettangoli attorno a ciascun componente (e subcomponenti) nel mock e dare un nome a ciascuno di essi. Se stai lavorando con i designer, potrebbero averlo già fatto, quindi parla anzitutto con loro! I nomi dei loro layer di Photoshop potrebbero finire per diventare i nomi dei tuoi componenti React!

- -

Come fai tuttavia a sapere cosa dovrebbe essere un componente a sé? Usa una delle tecniche per decidere se devi creare un nuovo oggetto o una nuova funzione. Una di tali tecniche è il principio della singola responsibilità, ovvero, un componente dovrebbe idealmente servire a un solo scopo. Se finisce per crescere, dovrebbe essere decomposto in componenti più piccoli.

- -

Dal momento che stai spesso mostrando un modello di dati JSON all'utente, ti accorgerai che se il tuo modello è stato costruito correttamente, la tua UI (e quindi anche la struttura dei tuoi componenti) si adatterà facilmente. Ciò accade perché le UI e i modelli di dati tendono ad aderire alla medesima architettura dell'informazione, che significa che il compito di separare la tua UI in componenti è spesso banale. Suddividila semplicemente in componenti che rappresentano esattamente un frammento del tuo modello di dati.

- -

Diagramma dei componenti

- -

Vedrai che abbiamo in tutto cinque componenti nella nostra semplice applicazione. Ho scritto in corsivo i dati che ciascun componente rappresenta.

- -
    -
  1. FilterableProductTable (arancione): contiene l'intero esempio
  2. -
  3. SearchBar (blu): riceve tutti gli input dell'utente
  4. -
  5. ProductTable (verde): mostra e filtra la collezione dei dati basandosi sull'input dell'utente
  6. -
  7. ProductCategoryRow (turchese): mostra un titolo per ciascuna categoria
  8. -
  9. ProductRow (rosso): mostra una riga per ciascun prodotto
  10. -
- -

Se osservi la ProductTable, ti accorgerai che l'intestazione della tabella (che contiene le etichette "Name" e "Price") non è un componente a sé. Questa è una questione di gusti, e ci sono ragioni valide per ciascun approccio. Per questo esempio, l'ho lasciata parte di ProductTable perché fa parte della visualizzazione della collezione dei dati che è la responsabilità di ProductTable. Tuttavia, se questa intestazione cresce fino a diventare complessa (cioè se dovessimo aggiungere la possibilità di riordinare i dati), avrebbe certamente senso renderla un componente ProductTableHeader a sé.

- -

Adesso che abbiamo identificato i componenti nel nostro mock, organizziamoli in una gerarchia. Questo è un compito facile. I componenti che appaiono all'interno di un altro componente nel the mock devono apparire come figli nella gerarchia:

- -
    -
  • FilterableProductTable - -
      -
    • SearchBar
    • -
    • ProductTable - -
        -
      • ProductCategoryRow
      • -
      • ProductRow
      • -
    • -
  • -
-

Passo 2: Costruisci una versione statica in React #

- - -

Adesso che hai la tua gerarchia di componenti, è venuto il momento di implementare la tua applicazione. La maniera più semplice è costruire una versione che prende il tuo modello di dati e visualizza la UI ma non è interattiva. È buona norma disaccoppiare questi processi perché costruire una versione statica richiede la scrittura di parecchio codice e poco pensare, mentre aggiungere l'interattività richiede un parecchio pensare ma non un granché di scrittura. Vedremo perché.

- -

Per costruire una versione statica della tua applicazione dhe visualizzi il tuo modello dei dati, vorrai costruire componenti che riutilizano altri componenti e passano loro dati usando le props. Le props sono una maniera di passare dati da genitore a figlio. Se hai dimestichezza con il concetto di state, non usare lo stato per costruire questa versione statica. Lo stato è riservato solo per l'interattività, cioè dati che cambiano nel tempo. Dal momento che questa è una versione statica dell'applicazione, non ne avrai bisogno.

- -

Puoi costruire dall'alto in basso, o dal basso in alto. Ovvero, puoi cominciare a costruire i componenti più in alto nella gerarchia (cioè cominciare con FilterableProductTable) oppure con quelli più in basso (ProductRow). In esempi più semplici, è solitamente più facile andare dall'alto in basso, mentre in progetti più grandi è più facile andare dal basso in alto e scrivere test mentre costruisci.

- -

Alla fine di questo passo avrai una libreria di componenti riutilizzabili che visualizzano il tuo modello dati. I componenti avranno soltanto metodi render() dal momento che questa è una versione statica della tua applicazione. Il componente al vertice della gerarchia (FilterableProductTable) prenderà il tuo modello dati come una proprietà. Se apporti un cambiamento al tuo modello dati sottostante e chiami nuovamente ReactDOM.render(), la UI sarà aggiornata. È facile vedere come la tua UI viene aggiornata e dove applicare cambiamenti dal momento che non c'è nulla di complicato. Il flusso dati unidirezionale di React (detto anche binding unidirezionale) mantiene tutto modulare e veloce.

- -

Fai riferimento alla documentazione React se hai bisogno di aiuto nell'eseguire questo passo.

-

Un breve intermezzo: proprietà oppure stato #

-

Esistono due tipi di dati "modello" in React: proprietà e stato. È importante capire la distinzione tra i due; scorri la documentazione ufficiale di React se non hai ben chiara la differenza.

-

Passo 3: Identifica la rappresentazione minima (ma completa) dello stato della UI #

-

Per rendere la tua UI interattiva, hai bisogno di poter scatenare cambiamenti al tuo modello dati sottostante. React lo rende facile tramite lo stato.

- -

Per costruire correttamente la tua applicaizone, devi prima pensare all'insieme minimo di stato mutevole di cui la tua applicazione ha bisogno. La chiave qui è il principio DRY: Don't Repeat Yourself (Non ripeterti). Una volta compresa la rappresentazione minima in assoluto dello stato della tua applicazione e calcola tutto lil resto sul momento. Ad esempio, se stai costruendo una lista di cose da fare, mantieni un array delle cose da fare; non tenere una variabile di stato separata per il conteggio. Invece, quando vuoi visualizzare il conteggio degli elementi, prendi semplicemente la lunghezza dell'arraiy delle cose da fare.

- -

Pensa a tutti gli elementi di dati nella nostra applicazione di esempio. Abbiamo:

- -
    -
  • La lista originaria dei prodotti
  • -
  • Il testo di ricerca che l'utente ha introdotto
  • -
  • Il valore del checkbox
  • -
  • La lista filtrata dei prodotti
  • -
- -

Rivediamo ciascuno di essi e capiamo se si tratta di stato. Chiediti queste tre semplici domande su ciascun elemento di dati:

- -
    -
  1. Viene passato da un genitore attraverso le proprietà? Se sì, probabilmente non è stato.
  2. -
  3. Cambia nel tempo? Se no, probabilmente non è stato.
  4. -
  5. Puoi calcolarlo basandoti su altro stato o proprietà del tuo componente? Se sì, non è stato.
  6. -
- -

La lista originaria di prodotti viene passata come proprietà, quindi non si tratta di stato. Il testo di ricerca e la checkbox sembrano essere stato perché cambiano nel tempo e non possono essere ricavate da altri dati. Infine, la lista filtrata di prodotti non è stato, perché può essere calcolata combinando la lista originaria dei prodotti con il testo di ricerca e il valore della checkbox.

- -

Quindi, per concludere, il nostro stato è:

- -
    -
  • Il testo di ricerca che l'utente ha introdotto
  • -
  • Il valore del checkbox
  • -
-

Passo 4: Identifica dove debba risiedere il tuo stato #

- - -

OK, abbiamo dunque identificato quale sia l'insieme minimo dello stato dell'applicazione. Successivamente, dobbiamo identificare quale componente muta, o possiede, questo stato.

- -

Ricorda: React è basato esclusivamente su flusso dati unidirezionale verso il basso della gerarchia dei componenti. Potrebbe non essere immediatamente chiaro quale componente debba possedere quale stato. Questa è spesso la parte più difficile da capire per i principianti, quindi segui questi passi per capirlo:

- -

Per ogni elemento dello stato nella tua applicazione:

- -
    -
  • Identifica ciascun componente che visualizza qualcosa basato su quello stato.
  • -
  • Trova un componente proprietario comune (un singolo componente più in alto nella gerarchia di ciascun componente che ha bisogno dello stato).
  • -
  • Il proprietario comune o un altro componente più in alto nella gerarchia deve possedere lo stato.
  • -
  • Se non riesci a trovare un componente per cui abbia senso possedere lo stato, crea un nuovo componente con il solo scopo di contenere lo stato e aggiungilo da qualche parte nella gerarchia sopra il componente proprietario comune.
  • -
- -

Applichiamo questa strategia per la nostra applicazione:

- -
    -
  • ProductTable deve filtrare la lista dei prodotti basandosi sullo stato e SearchBar deve visualizzare il testo di ricerca e lo stato della checkbox.
  • -
  • Il componente proprietario comune è FilterableProductTable.
  • -
  • Ha concettualmente senso che il testo di ricerca e lo stato della checkbox appartengano a FilterableProductTable
  • -
- -

Bene, abbiamo deciso che il nostro stato appartenga a FilterableProductTable. Anzitutto aggiungiamo un metodo getInitialState() a FilterableProductTable che restituisce {filterText: '', inStockOnly: false} per riflettere lo stato iniziale della tua applicazione. Dunque, passiamo filterText e inStockOnly a ProductTable e SearchBar come una proprietà. Infine, usiamo queste proprietà per filtrare le righe in ProductTable e impostare i valori dei campi del modulo in SearchBar.

- -

Puoi cominciare a vedere come si comporterà la tua applicazione: imposta filterText a "ball" e aggiorna la tua applicazione. Vedrai che la tabella dei dati è correttamente aggiornata.

-

Passo 5: Aggiungi il flusso dati inverso #

- - -

Finora abbiamo costruito un'applicazione che visualizza correttamente come una funzione di proprietà e stato che fluiscono verso il basso della gerarchia. Adesso è il momento di supportare il flusso dei dati nella direzione opposta: i componenti del modulo in profondità nella gerarchia devono aggiornare lo stato in FilterableProductTable.

- -

React rende questo flusso dati esplicito per rendere più semplice la comprensione di come funziona la tua applicazione, ma richiede leggermente più codice di un tradizionale binding bidirezionale dei dati. React offre un add-on chiamato ReactLink per rendere questo pattern altrettanto conveniente del binding bidirezionale ma, per gli scopi di questo articolo, faremo tutto in modo esplicito.

- -

Se provi a scrivere o spunti la casella nella versione attuale dell'esempio, vedrai che React ignora il tuo input. Questo è un comportamento intenzionale, in quanto abbiamo impostato la proprietà value del campo input perché sia sempre uguale al valore di state passato da FilterableProductTable.

- -

Pensiamo a cosa vogliamo che accada. Vogliamo assicurarci che quando l'utente cambia il modulo noi aggiorniamo lo stato per riflettere l'input dell'utente. Dal momento che i componenti devono soltanto aggiornare il proprio stato, FilterableProductTable passerà una callback a SearchBar che sarà eseguita quando lo stato debba essere aggiornato. Possiamo utilizzare l'evento onChange sui campi di input per esserne notificati. E la callback passata da FilterableProductTable chiamerà setState(), e l'applicazione verrà aggiornata.

- -

Anche se sembra complesso, si tratta realmente di poche righe di codice. Inoltre, il flusso dati attraverso l'applicazione è davvero esplicito.

-

Tutto qui #

-

Speriamo che questo ti abbia dato un'idea di come pensare a costruire componenti e applicazioni con React. Mentre potrebbe richiedere leggermente più codice di quanto si sia abituati a scrivere, ricorda che il codice è letto più spesso di quanto sia scritto, ed è estremamente facile leggere codice così esplicito e modulare. Mentre ti avvii a costruire grandi librerie di componenti, apprezzerai questa chiarezza e modularità, e con il riutilizzo del codice le tue righe di codice cominceranno a ridursi. :)

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/thinking-in-react-ja-JP.html b/docs/thinking-in-react-ja-JP.html deleted file mode 100644 index 1bec4d46e1..0000000000 --- a/docs/thinking-in-react-ja-JP.html +++ /dev/null @@ -1,638 +0,0 @@ - - - - - - - Reactの考え方 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Reactの考え方 -

-
- -

Pete Hunt著

- -

ReactはJavascriptで大きなアプリを早く作成するのに良い方法だと私は思います。FacebookとInstagram製で規模を大きすすることも容易いです。

- -

Reactのたくさんある中の偉大なパーツの1つのは、あなたに構築するアプリについて考えさせます。このページで、私はReactを使って検索可能な製品データテーブルを構築する思考プロセスをご案内します。

-

モックから始めましょう #

-

私たちはすでにデザイナーからJSON APIとモックをもらっていると想像してください。このモックを見ればわかるように私たちのデザイナーは明らかに良くないです。

- -

Mockup

- -

JSON APIはこれらのようなデータを返します。

-
[
-  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
-  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
-  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
-  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
-  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
-  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
-];
-

ステップ1 : コンポーネント階層を用いてUIを改築します #

-

まずあなたが行いたいことは、モックに必要なすべてのコンポーネント(サブコンポーネントも)の箱を作り、名前をつけることでしょう。もしあなたがデザイナーと共に働いているなら、すでに行っているかもしれませんが、彼らと話に行きましょう!彼らのPhotoshopのレイヤーの名前をReactのコンポーネントの名前にして終わらせることもできます。

- -

独自コンポーネントがどのようにあるべきか知っていますか? あなたが新しい関数やオブジェクトを作る必要があるかどうかを決定するために同じ技術を使用しています。そのうちの一つのテクニックが単一責任の原則(single responsibility principle)です。これは一つのコンポーネントは一つの振る舞いをするべきというものです。もしこれが難しいのであれば、より小さなサブコンポーネントに分ける必要があります。

- -

あなたは多くの場合、ユーザーにJSONデータ・モデルを表示しているので、あなたのモデルが正しく構築された場合、あなたのUI (したがって、コンポーネントの構造)がうまくマッピングされることがわかります。なぜなら、UIとデータモデルは同じ情報構造を持つ傾向にあり、つまりコンポーネントにUIを分離する作業は些細なことです。あなたの一つのデータモデルを表すコンポーネントに分割することが重要です。

- -

Component diagram

- -

これは私たちのシンプルなアプリの5つのコンポーネントです。各コンポーネントが表すデータが斜体になっています。

- -
    -
  1. FilterableProductTable (orange): 例のすべてを含んでいます。
  2. -
  3. SearchBar (blue): ユーザー入力のすべてを含んでいます。
  4. -
  5. ProductTable (green): displays and filters the ユーザー入力に基づいたデータコレクションを表示、選別します
  6. -
  7. ProductCategoryRow (turquoise): カテゴリーごとに表示します。
  8. -
  9. ProductRow (red): 製品の行ごとに表示します。
  10. -
- -

ProductTableを見ると、テーブルのヘッダー("Name"と"Price"ラベルを含んでいる)が独自コンポーネントではないとわかります。これは好みの問題で、どちらの方法が良いかの議論があります。この例では、ProductTableの責任の範囲であるデータ収集レンダリングの一部であるため、私はProductTableの一部として残しました。しかし、もしこのヘッダーが複雑になりそうであれば、(ソートにアフォーダンスを追加した場合など)新しい ProductTableHeader という独自コンポーネントを作る意味が高まります。

- -

私たちは自分たちのモックのコンポーネントを特定し、階層に配置してみましょう。これらは簡単です。モックの中の他のコンポーネントと一緒に使用するコンポーネントはその子供の階層にいなくてはいけません。

- -
    -
  • FilterableProductTable - -
      -
    • SearchBar
    • -
    • ProductTable - -
        -
      • ProductCategoryRow
      • -
      • ProductRow
      • -
    • -
  • -
-

ステップ2 : 静的なReactの構築 #

- - -

あなたは今コンポーネントの階層を持っており、アプリを実装する時がきました。最も簡単な方法はあなたの持っているデータモデルを受け取りUIをレンダリングするが、双方向性を持っていないバージョンを構築することです。静的なバージョンを構築するには多くのコードを書く必要があるが考えることはなく、双方向性を加えるためには熟考する必要がありコード量は多くないです。そのためこれらのプロセスは分離するのが最善の手段です。理由をみていきましょう。

- -

データモデルをレンダリングさせる静的なバージョンを構築するために、あなたは他のコンポーネントを再利用したり、propsを使用してコンポーネントを構築したいと思うでしょう。propsとは親から子へデータを受け渡す方法のことです。もしあなたがstateのことを知っているなら、この静的なバージョンを構築する際には絶対にstateは使わないでください。stateは双方向性のためにのみ予約されます。それはつまり、時間の経過とともにデータが変化していきます。静的なバージョンのアプリを作っている間はこれは必要のないものです。

- -

あなたはトップダウンでもボトムアップでも構築することができます。つまりあなたは階層の高い場所から(FilterableProductTable)でも、低い場所から(ProductRow)でもコンポーネントを構築し始めることができます。簡単な例ではトップダウンから行く方が簡単ですし、大規模なプロジェクトではボトムアップを行って、構築するテストを書く方が簡単です。

- -

この最後のステップは、データモデルをレンダリングできる再利用可能なコンポーネントのライブラリーを手に入れることです。これはあなたのアプリの静的なバージョンのため、コンポーネントはrender()メソッドのみを持ちます。階層のトップのコンポーネント(FilterableProductTable)は部品としてデータモデルを持ちます。あなたが下の階層にあるデータモデルの変更を行い、ReactDOM.render()を呼ぶと、UIも更新されます。複雑なことは何もないので、どのようにあなたのUIが更新され、変更した場所を確認するのは簡単です。Reactの1方向のデータフロー (1方向バインディングともよばれます。)はすべてのモジュール式と速さを保ちます。

- -

このステップでヘルプが必要な場合はここに簡単な説明があります。React docs

-

コラム: props か state か? #

-

Reactにはpropsとstateの2つのタイプの"model"データがあります。この二つの違いを理解することは重要です。違いを明確に理解していない場合はここを参照してください。the official React docs

-

ステップ3 : UI部品の最小限の(しかし完全な)表現を特定します #

-

UIをインタラクティブに作るために、下の階層のデータモデルを変更を行えるようにする必要があります。Reactでは state を使うことで簡単に行うことができます。

- -

アプリの構築を正しく行うために、まずそのアプリのニーズの可変状態の最小セットを考える必要があります。ここで重要なのはDRY、つまり繰り返さないこと、です。アプリケーションの状態の絶対的な最小表現を把握し、オンデマンドで必要他のすべてを計算します。たとえば、TODOリストを構築するとすると、TODOのリストを配列で保持し、個別にカウントの状態変数を保持しません。TODOの個数をレンダリングするときに、単にTODOのアイテムの長さを取得すればよいのです。

- -

今回のアプリケーションのデータのすべてを考えます。私たちは以下を持っています。

- -
    -
  • 独自製品のリスト
  • -
  • ユーザーが入力した検索テキスト
  • -
  • チェックボックスの値
  • -
  • 製品のフィルターリスト
  • -
- -

それぞれ一つを通し、それぞれの状態を把握しましょう。それぞれのデータに尋ねる質問は3つです。

- -
    -
  1. それはpropを経由して、親から渡されますか?そうなら、おそらくstateではありません。
  2. -
  3. それは時間の経過とともに変化しますか?そうでないなら、おそらくstateではありません。
  4. -
  5. あなたはそれがコンポーネント内の他のstateやpropに基づいて計算することができますか?そうなら、おそらくstateではありません。
  6. -
- -

その製品の独自のリストはpropとして渡されるので、stateではありません。検索テキストとチェックボックスは時間の経過とともに変化し、それを計算することはできないので、stateのように見えます。最後に、検索テキストとチェックボックスの値を持つ製品の独自のリストを組み合わせることによって計算することができるため、製品のフィルタリングされたリストはstateではありません。

- -

つまり最終的にstateはこうなります。

- -
    -
  • ユーザーが入力した検索テキスト
  • -
  • チェックボックスの値
  • -
-

ステップ4 : あなたのstateがあるべき場所を特定します。 #

- - -

ここまでで、私たちはアプリの状態の最小セットが何であるかを認識することができました。次はコンポーネントの変化か、またはそれ自身の状態を特定する必要があります。

- -

メモ:Reactはすべてのデータがコンポーネントの階層が1方向に流れるものです。コンポーネントがどのような状況にあるかはすぐには明確にはならないかもしれません。** これはしばしば新しく学ぼうとする方には難しいものになるため** 把握するために次の手順に従います。

- -

アプリ内のそれぞれのstate

- -
    -
  • 幾つかのstateに基づくレンダリングをするすべてのコンポーネントを識別する
  • -
  • 共通の所有者を持つコンポーネント(階層内のstateを必要にするすべてのコンポーネント上にあるコンポーネント)
  • -
  • 階層内の最大の、共通の所有者または別のコンポーネントのいずれか
  • -
  • 意味のあるstateにコンポーネントを見つけることができない場合には、状態を保持するために、単純に新しいコンポーネントを作成し共通の所有者のコンポーネント上の階層のどこかに追加します。
  • -
- -

アプリケーションのためにこの戦略に沿って実行しましょう

- -
    -
  • ProductTableはstateに基づいた製品リストのフィルターを必要とし、 SearchBarは検索テキストとチェックの状態を表示する必要があります。
  • -
  • 共通のコンポーネントの所有者はFilterableProductTableです。
  • -
  • FilterableProductTableにあるフィルタテキストと確認された値は概念的に理解する。
  • -
- -

stateはFilterableProductTableの中にあると決定しました。まずはアプリケーションの最初の状態を反映させるため、FilterableProductTable{filterText: '', inStockOnly: false}を返す、getInitialState()という関数を追加します。次に、ProductTableSearchBarにpropとしてfilterTextinStockOnlyを通します。最後にこれらのpropをProductTableの行のフィルターに使い、SearchBarのフォームのフィールドの値をセットします。

- -

アプリケーションがどのように動作("ball"filterTextをセットし、アプリを更新する)するかを見て開始することができます。データテーブルが正しく更新されていることがわかるでしょう。

-

ステップ5 : 逆のデータフローを追加 #

- - -

ここまで、階層の下へ向かってpropやstateの関数として正しくレンダリングするアプリを構築しました。ここからは逆の方向へのデータのフローをサポートします。深い階層のフォームのコンポーネントはFilterableProductTableのstateを更新する必要があります。

- -

Reactは、このデータの流れがどのようにあなたのプログラムが動くのかの理解を簡単にする流れですが、それが伝統的な双方向のデータバインディングよりも少しタイピングを必要とします。ReactはReactLinkという双方向バインディングを便利に実装できるアドオンを提供していますが、この投稿の目的は私たちが全てを明確にすることです。

- -

例えば、あなたが入力するか現在のバージョンのチェックボックスをオンにしようとすると、あなたの入力をReactは無視することがわかります。これは意図的なもので、私たちは常にFilterableProductTable から渡されたstateに等しくなるようにinputの値を設定しているためです。

- -

何を起こしたいのかを考えましょう。私たちは確かにユーザーがどのようにフォームを変えても入力した値をstateに反映させようとしています。コンポーネントが自身のstateを更新する必要があるため、FilterableProductTableSearchBarが更新するべき時にはいつでもコールバックを渡します。入力の通知に対してonChangeイベントを使用できます。そしてFilterableProductTableによって渡されたコールバックはsetState()を呼び出し、アプリが更新されます。

- -

これは複雑に見えますが、それはわずか数行のコードのみです。そしてデータがどのようにアプリ内を流れているか、とても明白です。

-

以上です。 #

-

この記事を通してReactでコンポーネントとアプリケーションを構築するかをどのように考えるかのヒントになれば幸いです。あなたが今まで使ってきたものよりも少しタイピングが必要かもしれないが、そのコードは書かれているよりもはるかに多くを認識し、このモジュールを読むためにとても簡単でかつ明白なコードです。あなたが大きなコンポーネントのライブラリを構築するのなら、この明示性とモジュール性に感謝するでしょうし、コードの再利用性とコードのあなたのラインが縮小し始めます。 :)

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/thinking-in-react-ko-KR.html b/docs/thinking-in-react-ko-KR.html deleted file mode 100644 index 2e42151830..0000000000 --- a/docs/thinking-in-react-ko-KR.html +++ /dev/null @@ -1,638 +0,0 @@ - - - - - - - 리액트로 생각해보기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 리액트로 생각해보기 -

-
- -

Pete Hunt의 글입니다.

- -

제가 생각하기에, React는 JavaScript로 크고 빠른 웹 애플리케이션을 만드는데 최고입니다. 페이스북과 인스타그램에서 우리에게 잘 맞도록 조정되어 왔습니다.

- -

React의 많은 뛰어난 점들 중 하나는 생각을 하면서 애플리케이션을 만들게 한다는 겁니다. 이 포스트에서, React를 이용해 검색이 가능한 상품자료 테이블을 만드는 생각 과정을 이해할 수 있게 차근차근 설명할 겁니다.

-

모형으로 시작해보기 #

-

우리가 이미 JSON API와 디자이너로부터 넘겨받은 모형을 이미 가지고 있다고 생각해봅시다. 보시다시피 우리 디자이너는 별로 좋지 않습니다:

- -

Mockup

- -

우리의 JSON API는 아래와 같은 데이터를 리턴합니다:

-
[
-  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
-  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
-  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
-  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
-  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
-  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
-];
-

1단계: UI를 계층 구조의 컴포넌트로 분쇄하세요. #

-

당신이 하고싶은 첫번째는 모형에 있는 모든 컴포넌트 (그리고 자식엘리먼트) 주위에 상자를 그리고, 이름을 부여하는 것입니다. 만약 당신이 디자이너와 같이 작업중이라면, 그들은 이미 이 작업을 해놨을지도 모릅니다. 당장 가서 이야기해보세요. 그들의 포토샵 레이어 이름이 결국 당신의 React 컴포넌트들의 이름이 될 것입니다.

- -

그런데 무엇이 컴포넌트가 되어야 할까요? 당신이 새로운 함수나 객체를 만들어야만 한다면, 똑같이 적용하세요. 한가지 방법은 단일 책임의 원칙 입니다. 즉 하나의 컴포넌트는 이상적으로 한가지 작업만 수행해야 합니다. 컴포넌트가 결국 커진다면, 작은 자식 컴포넌트로 쪼개져야 합니다.

- -

주로 JSON 데이터 모델을 사용자에게 보여주기 때문에, 자료 모델이 잘 설계 되었다면, UI(혹은 컴포넌트 구조)가 잘 맞아 떨어진다는 것을 알게 될 겁니다. UI와 자료 모델은 같은 정보 설계구조로 따라가는 경향이 있기 때문입니다. 즉, UI를 컴포넌트들로 쪼개는 작업은 크게 어렵지 않습니다. 확실하게 각각 하나의 부분이 되도록 쪼개세요.

- -

Component diagram

- -

이 간단한 애플리케이션에는 다섯개의 컴포넌트가 있습니다. 각 컴포넌트들이 대표하는 자료를 기울여 표기했습니다.

- -
    -
  1. FilterableProductTable (오렌지): 예제 전부를 포함합니다.
  2. -
  3. SearchBar (파랑): 모든 사용자 입력 을 받습니다.
  4. -
  5. ProductTable (초록): 자료 모음사용자 입력에 맞게 거르고 보여줍니다.
  6. -
  7. ProductCategoryRow (청록):카테고리의 제목을 보여줍니다.
  8. -
  9. ProductRow (빨강):프로덕트를 보여줍니다.
  10. -
- -

ProductTable을 보면, 테이블 제목("Name", "Price" 라벨들을 포함한)은 컴포넌트가 아닌것을 알 수 있습니다. 이건 기호의 문제이고, 어느쪽으로 만들던 논쟁거리입니다. 이 예제에서는, 저는 자료 모음을 그리는 ProductTable의 의무라고 생각했기 때문에 남겨 두었습니다. 하지만, 이 제목이 복잡해진다면 (예를 들어 정렬을 추가할 여유가 있다거나 하는), 이건 확실히 ProductTableHeader 컴포넌트로 만드는 것이 맞을 겁니다.

- -

이제 모형에 들어있는 컴포넌트들에 대해 알아보았으니, 계층 구조로 만들어 봅시다. 이건 쉽습니다. 다른 컴포넌트 속에 들어있는 컴포넌트를 자식으로 나타내기만 하면 됩니다.

- -
    -
  • FilterableProductTable - -
      -
    • SearchBar
    • -
    • ProductTable - -
        -
      • ProductCategoryRow
      • -
      • ProductRow
      • -
    • -
  • -
-

2단계: 정적 버전을 만드세요. #

- - -

계층구조의 컴포넌트들을 가지고 있으니, 이젠 애플리케이션을 구현할 시간입니다. 가장 쉬운 방법은 상호작용을 하지 않는 채로 자료 모델을 이용해 UI를 그리는 것입니다. 정적 버전을 만드는 데에는 적은 생각과 많은 노동이 필요하고, 상호작용을 추가하는 데에는 많은 생각과 적은 노동이 필요하기 때문에 둘을 분리하는 것이 가장 좋습니다. 왜 그런지 봅시다.

- -

자료 모델을 그리는 애플리케이션의 정적버전을 만들기 위해서, 다른 컴포넌트에 재사용할 컴포넌트를 만들고 자료 전달을 위해 props를 사용하고 싶을 것입니다. 만약 상태라는 개념에 익숙하다면, 정적 버전을 만들때 절대 상태를 사용하지 마세요. 상태는 오직 상호작용, 즉 가변적인 자료를 위해서만 준비되어 있습니다. 정적 버전을 만들 때는 필요가 없습니다.

- -

껍데기부터 혹은 속알맹이부터 만들 수 있습니다. 즉 계층구조상 위에서부터 (FilterableProductTable 부터) 혹은 아래에서부터 (ProductRow), 어느 방향에서든 시작해도 됩니다. 통상 큰 프로젝트에서는 계층구조상 위에서부터 시작하는 것이 쉽고, 테스트를 작성할때는, 아래에서부터 시작하는 것이 쉽습니다.

- -

이 단계의 결과, 자료 모델을 그리는 재활용 가능한 컴포넌트의 라이브러리를 갖게 되었습니다. 정적버전 이후로 컴포넌트들은 오직 render() 메소드만 갖고 있습니다. 계층구조상 가장 위의 컴포넌트 (FilterableProductTable)은 자료 모델을 prop으로 취할 것입니다. 자료 모델이 변했을 때, ReactDOM.render()를 다시 부르면 UI가 업데이트 됩니다. 어떻게 UI가 업데이트 되는지 참 알기 쉽습니다. 자료가 바뀌어도 처리해야 할 복잡한 일이 아무것도 없습니다. React의 단일 방향 자료 흐름 (혹은 단일방향 바인딩)이 모든것을 모듈식으로, 추론하기 쉽게, 그리고 빠르게 유지해줍니다.

- -

이 단계를 진행하는 데에 도움이 필요하시다면, React 문서를 참조하세요.

-

잠시만: props vs state #

-

React 에는 두가지 타입의 자료 "모델"이 있습니다: props 와 state. 두가지의 구분점을 이해하는데 매우 중요합니다; 혹시 차이점을 확신하지 못한다면 걷어내세요 공식 문서.

-

3단계: UI state 의 표현을 작지만 완전하도록 확인하세요. #

-

상호적인 UI를 만들기 위해서는, 자료 모델 변화에 반응할 수 있어야 합니다. React는 state로 이걸 쉽게 만들어주죠.

- -

올바르게 애플리케이션을 만들기 위해서는, 첫째로 애플리케이션에 필요한 변할 수 있는 state 들의 최소한의 집합에 대해서 생각해볼 필요가 있습니다. 여기 방법이 있습니다: 스스로 반복하지 마세요 (DRY). 애플리케이션의 상태를 나타낼 수 있는 가장 최소한의 표현 방식을 찾고, 그 밖의 것은 필요할 때 계산합니다. 예를들어 TODO 목록를 만든다고 칩시다. TODO 아이템들의 배열만 유지하세요; 갯수를 표현하기 위한 state 변수를 분리하지 마세요. 대신 TODO 아이템들 배열의 길이를 이용하세요.

- -

예제 애플리케이션에서의 모든 자료유형에 대해 생각해 봅시다:

- -
    -
  • product 들의 원본 목록
  • -
  • 사용자가 입력한 검색어
  • -
  • 체크박스의 값
  • -
  • product 들의 필터된 목록
  • -
- -

어느것이 state 가 될지 따져봅시다. 간단하게 각 자료에 대해 세가지만 생각해 보세요.

- -
    -
  1. 만약 부모로부터 props 를 이용해 전달됩니까? 그렇다면 이건 state가 아닙니다.
  2. -
  3. 종종 바뀝니까? 아니라면 이것 역시 state가 아닙니다.
  4. -
  5. 컴포넌트에 있는 다른 state나 props를 통해서 계산되어질 수 있습니까? 역시 state가 아닙니다.
  6. -
- -

product 들의 원본 목록은 props를 통해서 전달되기 때문에, state가 아닙니다. 검색어와 체크박스의 값은 다른것에 의해 계산될 수 있는 값이 아니고, 시시각각 변하기때문에 state가 맞습니다. 마지막으로 product 들의 걸러진 목록 역시 state가 아닙니다. 원본 목록과 검색어, 체크박스의 값 등에 의해 연산되어지는 값이기 때문이죠.

- -

결국, state는 다음과 같습니다:

- -
    -
  • 사용자가 입력한 검색어
  • -
  • 체크박스의 값
  • -
-

4단계: 어디서 state가 유지되어야 하는지 확인하세요. #

- - -

이제 최소한의 state가 무엇인지 알아냈습니다. 다음은, 어떤 컴포넌트가 이 state를 변형하거나 만들어낼지 알아내야 합니다.

- -

기억하세요: React는 계층적 아래 컴포넌트로만 향하는 단일방향성 자료 흐름을 가집니다. 지금당장은 어떤 컴포넌트가 자기 자신의 state를 가져야 할지 명확하지 않을 것입니다. 이것이 초심자가 가장 이해하기 어려운 부분입니다. 이제 개념을 명확히 하기 위해 다음으로 따라가 봅시다:

- -

애플리케이션에서 state의 경우:

- -
    -
  • 모든 컴포넌트가 state를 통해 무언가를 그려냅니다.
  • -
  • 대표 컴포넌트가 뭔지 찾으세요 (계층적으로 다른 컴포넌트들의 단일 상위 컴포넌트는 state를 가질 필요가 있습니다).
  • -
  • 대표 컴포넌트 혹은 또다른 컴포넌트는 가능한 상위의 컴포넌트가 state를 소유해야 합니다.
  • -
  • 만약 state를 가져야할 컴포넌트가 어느 것인지 모르겠으면, 새로운 컴포넌트를 만들어 state를 부여하고 기존의 대표 컴포넌트 위에 추가하세요.
  • -
- -

이 전략을 우리 애플리케이션에 적용해 봅시다.

- -
    -
  • ProductTable은 state에 대해 걸러질 필요가 있고, SearchBar 역시 검색어 state와 체크박스 state를 보여줄 필요가 있습니다.
  • -
  • 대표 컴포넌트는 FilterableProductTable 입니다.
  • -
  • 개념적으로 검색어와 체크박스 값은 FilterableProductTable에 있어야 한다는 것이 명확합니다.
  • -
- -

좋습니다. state를 FilterableProductTable에서 관리하도록 결정했습니다. 먼저, getInitialState() 메소드를 FilterableProductTable에 추가하세요. 이 메소드는 애플리케이션의 초기 state를 갖도록 {filterText: '', inStockOnly: false}를 리턴하면 됩니다. 그리고, filterTextinStockOnlyProductTableSearchBar에 prop으로 전달하세요. 마지막으로, 이 prop들을 ProductTable을 걸러내는 데, 그리고 SearchBar form fields의 값을 세팅하는데 사용하세요.

- -

이제 어떻게 애플리케이션이 동작하는지 볼 수 있습니다: filterText"ball"로 설정하고 업데이트합니다. 자료 테이블이 제대로 업데이트 되는 것을 볼 수 있을 겁니다.

-

5단계: 반대방향 자료 흐름을 추가하세요. #

- - -

앞서 우리는 계층적으로 아랫방향 흐름의 props, state전달로 잘 동작하는 애플리케이션을 만들었습니다. 이제 다른방향의 자료 흐름을 지원할 시간입니다: form 컴포넌트들은 FilterableProductTable의 state를 업데이트할 필요성이 있죠.

- -

React는 어떻게 이 프로그램이 동작하는지 이해하기 쉽게 이 자료의 흐름을 명시적으로 만들어주지만 전통적인 두 방향의 자료 바인딩보다 다소 입력할 것이 많습니다. React는 이러한 패턴을 양방향 바인딩처럼 편하게 사용할 수 있도록 ReactLink를 제공하지만, 이 글의 목적상 명시적인 방식만 사용했습니다.

- -

지금 예제에 문자열을 입력하거나 체크박스를 체크하더라도, React가 입력을 무시하는것을 볼 수 있습니다. 의도적으로 input의 prop에 value를 세팅하면 항상 stateFilterableProductTable로부터 전달되어야 합니다.

- -

우리가 원하는 것이 무엇인지 생각해 봅시다. 사용자 입력을 반영하기 위해, 사용자가 form을 바꿀때마다 업데이트 하기를 원하죠. 컴포넌트들이 오직 자기 자신의 state만 업데이트 하더라도 FilterableProductTable은 state가 변할때마다 반영되어야할 SearchBar에 콜백을 전달할 것입니다. 이 알림을 위해서 onChange이벤트를 사용할 수 있습니다. 그리고 FilterableProductTable으로부터 전달된 콜백은 setState()를 호출할 것이고, 애플리케이션은 업데이트될 것입니다.

- -

복잡하게 들릴 수 있지만, 실제로는 몇 줄 되지 않습니다. 그리고 애플리케이션의 구석구석에서 데이터가 어떻게 흐르는지 매우 명확해집니다.

-

그리고 #

-

이 글이 컴포넌트와 React로 애플리케이션을 어떻게 만들지에 대한 아이디어가 되길 바랍니다. 원래 하던 방식보다 조금 타이핑을 더 해야할지도 모르지만, 코드는 쓰는 경우보다 읽히는 경우가 많다는 점, 매우 읽기 편하고 명시적인 코드를 썼다는 점을 기억하세요. 컴포넌트로 큰 라이브러리를 만들기 시작할 때, 이 명시성과 모듈성에 감사하게 될 것이며, 재사용함에 따라 코드의 양도 줄어들 것입니다. :)

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/thinking-in-react-zh-CN.html b/docs/thinking-in-react-zh-CN.html deleted file mode 100644 index c3d32808b2..0000000000 --- a/docs/thinking-in-react-zh-CN.html +++ /dev/null @@ -1,638 +0,0 @@ - - - - - - - React 编程思想 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- React 编程思想 -

-
- -

by Pete Hunt

- -

在我看来,React 是构建大型,快速 Web app 的首选方式。它已经在 Facebook 和 Instagram 被我们有了广泛的应用。

- -

React 许多优秀的部分之一,是它使得你在构建 app 的过程中不断思考。在本文里,我将带你经历一次使用 React 构建可搜索的商品数据表的思考过程。

-

从模型(mock)开始 #

-

想象我们已经有个一个 JSON API 和一个来自设计师的模型。我们的设计师显然做得不够好,因为模型看起来像这样:

- -

Mockup

- -

我们的 JSON API 返回一些看起来像这样的数据:

-
[
-  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
-  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
-  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
-  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
-  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
-  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
-];
-

第一步:把UI拆分为一个组件的层级 #

-

首先你想要做的,是在模型里的每一个组件周围绘制边框,并给它们命名。如果你和设计师一起工作,他们应该已经完成这步了,所以去和他们谈谈!他们的 Photoshop 图层名也许最终会成为你的 React 组件名。

- -

但是你如何知道什么东西应该是独立的组件?只需在你创建一个函数或者对象时,根据是否使用过相同技术来做决定。一种这样的技术是单一功能原则(single responsibility principle),也就是一个组件在理想情况下只做一件事情。如果它最终增长了,它就应该被分解为更小的组件。

- -

既然你频繁显示一个 JSON 的数据模型给用户,你会发现,如果你的模型构建正确,你的 UI(因此也有你的组件结构)就将映射良好。那是因为 UI 和数据模型趋向附着于相同的 信息架构,这意味着,把你的 UI 分离为组件的工作通常是琐碎的,只需把 UI 拆分成能准确对应数据模型的每块组件。

- -

Component diagram

- -

在这里你会看到,在我们的简单 APP 里有五个组件。我用斜体表示每个组件的数据。

- -
    -
  1. FilterableProductTable (橙色): 包含示例的整体
  2. -
  3. SearchBar (蓝色): 接收所有 用户输入
  4. -
  5. ProductTable (绿色): 基于 用户输入 显示和过滤 数据集合(data collection)
  6. -
  7. ProductCategoryRow (蓝绿色): 为每个 分类 显示一个列表头
  8. -
  9. ProductRow (红色): 为每个 商品 显示一行
  10. -
- -

如果你看着 ProductTable,你会看到表头(包含了 "Name" 和 "Price" 标签) 不是独立的组件。这是一个个人喜好问题,并且无论采用哪种方式都有争论。对于这个例子,我把它留做 ProductTable 的一部分,因为它是 data collection渲染的一部分,而 data collection 渲染是 ProductTable 的职责。然而,当列表头增长到复杂的时候(例如 如果我们添加排序功能),那么使它成为独立的 ProductTableHeader 组件无疑是有意义的。

- -

既然现在我们已经识别出了我们模型中的组件,让我们把他们安排到一个层级中。这很容易。在模型中,出现在一个组件里面的另一组件 ,应该在层级中表现为一种子级关系:

- -
    -
  • FilterableProductTable - -
      -
    • SearchBar
    • -
    • ProductTable - -
        -
      • ProductCategoryRow
      • -
      • ProductRow
      • -
    • -
  • -
-

第二步:用React创建一个静态版本 #

- - -

既然你已经有了你的组件层级,是时候实现你的app了。简单的方式是构建一个版本,它取走你的数据模型并渲染UI,除了没有互动性。这是将过程解耦的最好办法,因为构建一个静态版本需要不假思索地写很多代码,而添加互动性需要很多思考但不需要太多代码。之后我们将会看到原因。

- -

要构建一个静态版本 app 来渲染你的数据模型,你将会想到构建一个重用其它组件并利用 props 传递数据的组件。props 是一种从父级传递数据到子级的方式。如果你对 state 的观念很熟悉,绝不要用state 来构建这个静态版本。State 仅仅是为互动性,也就是随时间变化的数据所预留的。由于这是一个静态版本,你还不需要用到它。

- -

你可以自顶向下或自底向上的构建。也就是说,你可以既从较高的层级(比如从 FilterableProductTable 开始)也可以从较低的层级(ProductRow)开始构建组件。在较简单的例子里,通常自顶向下要容易一些,然而在更大的项目上,自底向上地构建更容易,并且更方便伴随着构建写测试。

- -

在这一步的最后,你会获得一个渲染数据模型的可重用组件库。这些组件只有 render() 方法,因为这是一个静态版本。在层级顶端的组件 (FilterableProductTable) 将会接受你的数据模型,并将其作为一个prop。如果你改变了底层数据模型,并且再次调用 React.render() ,UI 将会更新。你可以很容易地看到 UI 是如何更新的,以及哪里变动了,因为这没什么复杂的。React的 单向数据流 (也被称为 单向绑定)使一切保持了模块化和快速。

- -

如果你在执行这步时需要帮助,请参阅 React 文档

-

小插曲: props vs state #

-

在React里有两种数据 "模型": props 和 state。明白这二者之间的区别是很重要的;如果你不是很确定它们之间的区别,请概览React官方文档

-

第三步:确定最小(但完备)的 UI state 表达 #

-

要让你的 UI 互动,你需要做到触发底层数据模型发生变化。React用 state 来让此变得容易。

- -

要正确的构建你的 app,你首先需要思考你的 app 需要的可变 state 的最小组。这里的关键是 DRY 原则:Don't Repeat Yourself(不要重复自己)。想出哪些是你的应用需要的绝对最小 state 表达,并按需计算其他任何数据。例如,如果你要构建一个 TODO list,只要保持一个 TODO 项的数组;不要为了计数保持一个单独的 state 变量。当你想渲染 TODO 的计数时,简单的采用 TODO 项目的数组长度作为替代。

- -

考虑我们示例应用中的数据所有块,包括:

- -
    -
  • 原始的商品列表
  • -
  • 用户输入的搜索文本
  • -
  • 复选框的值
  • -
  • 商品的过滤列表
  • -
- -

让我们逐个检查出哪一个是state,只需要简单地问以下三个问题:

- -
    -
  1. 它是通过props从父级传递来的吗?如果是,它可能不是 state。
  2. -
  3. 它随时间变化吗?如果不是,它可能不是 state。
  4. -
  5. 你能基于其他任何组件里的 state 或者 props 计算出它吗?如果是,它可能不是state.
  6. -
- -

原始的商品列表以 props 传入,所以它不是 state。搜索文本和复选框看起来是 state,因为他们随时间变化并且不能从任何东西计算出。最后,过滤出的商品列表不是 state,因为它可以通过原始列表与搜索文本及复选框的值组合计算得出。

- -

所以最后,我们的 state 是:

- -
    -
  • 用户输入的搜索文本
  • -
  • checkbox 的值
  • -
-

第四步:确定你的 state 应该存在于哪里 #

- - -

OK,我们已经确定好应用的最小 state 集合是什么。接下来,我们需要确定哪个组件可以改变,或者 拥有 这个state.

- -

记住:React 总是在组件层级中单向数据流动的。可能不能立刻明白哪些组件应该拥有哪些 state。 这对于新手在理解上经常是最具挑战的一部分, 所以跟着这几步来弄明白它:

- -

对于你的应用里每一个数据块:

- -
    -
  • 确定哪些组件要基于 state 来渲染内容。
  • -
  • 找到一个共同的拥有者组件(在所有需要这个state组件的层次之上,找出共有的单一组件)。
  • -
  • 要么是共同拥有者,要么是其他在层级里更高级的组件应该拥有这个state。
  • -
  • 如果你不能找到一个组件让其可以有意义地拥有这个 state,可以简单地创建一个新的组件 hold 住这个state,并把它添加到比共同拥有者组件更高的层级上。
  • -
- -

让我们使用这个策略浏览一遍我们的应用:

- -
    -
  • ProductTable 需要基于 state 过滤产品列表,SearchBar 需要显示搜索文本和选择状态。
  • -
  • 共同拥有者组件是 FilterableProductTable
  • -
  • 对于过滤文本和选择框值存在于 FilterableProductTable,从概念上讲是有意义的。
  • -
- -

酷,我们已经决定了我们的 state 存在于 FilterableProductTable。首先,添加一个 getInitialState() 方法到 FilterableProductTable,返回 {filterText: '', inStockOnly: false} 来反映应用的初始状态。然后,传递filterTextinStockOnlyProductTableSearchBar 作为 prop。最后,使用这些 prop 来过滤 ProductTable 中的行和设置 SearchBar 的表单项的值。

- -

你可以开始看看你的应用将有怎样的行为了: 设置 filterText"ball" 并刷新你的 app。你将可以看到数据表被正确地更新。

-

第五步:添加反向数据流 #

- - -

到目前为止,我们已经构建了一个应用, 它以 props 和 state 沿着层级向下流动的功能正确渲染。现在是时候支持另一种数据流动了:在层级深处的表单组件需要更新 FilterableProductTable 里的 state。

- -

React 让数据显式流动,使你理解应用如何工作变得简单,但是相对于传统的双向数据绑定,确实需要多打一些字。React 提供了一个叫做 ReactLink 的插件来使这种模式和双向数据绑定一样方便,但是考虑到这篇文章的目的,我们将会保持所有东西都直截了当。

- -

如果你尝试在当前版本的示例中输入或者选中复选框,你会发现 React 忽略了你的输入。这是有意的,因为我们已经设置了 inputvalue prop 值总是与 FilterableProductTable 传递过来的 state 一致。

- -

让我们思考下希望发生什么。我们想确保每当用户改变表单,就通过更新 state 来反映用户的输入。由于组件应该只更新自己拥有的 state , FilterableProductTable 将会传递一个回调函数给 SearchBar ,每当 state 应被更新时回调函数就会被调用。我们可以使用 input 的 onChange 事件来接受它的通知。 FilterableProductTable 传递的回调函数将会调用 setState() ,然后应用将会被更新。

- -

虽然这听起来复杂,但是实际上只是数行代码。并且这明确显示出了数据在应用中从始至终是如何流动的。

-

好了,就是这样 #

-

希望这给了你一个怎样思考用React构建组件和应用的概念。虽然可能比你过往的习惯要多敲一点代码,但记住,读代码的时间远比写代码的时间多,并且阅读这种模块化的、显式的代码是极为容易的。当你开始构建大型组件库时,你会非常感激这种清晰性和模块化,并且随着代码的重用,你的代码行数将会开始缩减。:)

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/thinking-in-react.html b/docs/thinking-in-react.html index 8b4f8e198b..59b9470b3b 100644 --- a/docs/thinking-in-react.html +++ b/docs/thinking-in-react.html @@ -1,12 +1,14 @@ + + - Thinking in React | React - - + Thinking in React - React + + @@ -44,31 +46,192 @@
-
+
+ Edit on GitHub +

+ Thinking in React +

+
+ +

React is, in our opinion, the premier way to build big, fast Web apps with JavaScript. It has scaled very well for us at Facebook and Instagram.

+ +

One of the many great parts of React is how it makes you think about apps as you build them. In this document, we'll walk you through the thought process of building a searchable product data table using React.

+

Start With A Mock #

+

Imagine that we already have a JSON API and a mock from our designer. Our designer apparently isn't very good because the mock looks like this:

+ +

Mockup

+ +

Our JSON API returns some data that looks like this:

+
[
+  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
+  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
+  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
+  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
+  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
+  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
+];
+

Step 1: Break The UI Into A Component Hierarchy #

+

The first thing you'll want to do is to draw boxes around every component (and subcomponent) in the mock and give them all names. If you're working with a designer, they may have already done this, so go talk to them! Their Photoshop layer names may end up being the names of your React components!

+ +

But how do you know what should be its own component? Just use the same techniques for deciding if you should create a new function or object. One such technique is the single responsibility principle, that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents.

+ +

Since you're often displaying a JSON data model to a user, you'll find that if your model was built correctly, your UI (and therefore your component structure) will map nicely. That's because UI and data models tend to adhere to the same information architecture, which means the work of separating your UI into components is often trivial. Just break it up into components that represent exactly one piece of your data model.

+ +

Component diagram

+ +

You'll see here that we have five components in our simple app. We've italicized the data each component represents.

+ +
    +
  1. FilterableProductTable (orange): contains the entirety of the example
  2. +
  3. SearchBar (blue): receives all user input
  4. +
  5. ProductTable (green): displays and filters the data collection based on user input
  6. +
  7. ProductCategoryRow (turquoise): displays a heading for each category
  8. +
  9. ProductRow (red): displays a row for each product
  10. +
+ +

If you look at ProductTable, you'll see that the table header (containing the "Name" and "Price" labels) isn't its own component. This is a matter of preference, and there's an argument to be made either way. For this example, we left it as part of ProductTable because it is part of rendering the data collection which is ProductTable's responsibility. However, if this header grows to be complex (i.e. if we were to add affordances for sorting), it would certainly make sense to make this its own ProductTableHeader component.

+ +

Now that we've identified the components in our mock, let's arrange them into a hierarchy. This is easy. Components that appear within another component in the mock should appear as a child in the hierarchy:

+ +
    +
  • FilterableProductTable + +
      +
    • SearchBar
    • +
    • ProductTable + +
        +
      • ProductCategoryRow
      • +
      • ProductRow
      • +
    • +
  • +
+

Step 2: Build A Static Version in React #

+

See the Pen Thinking In React: Step 2 on CodePen.

+ + + +

Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why.

+ +

To build a static version of your app that renders your data model, you'll want to build components that reuse other components and pass data using props. props are a way of passing data from parent to child. If you're familiar with the concept of state, don't use state at all to build this static version. State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app, you don't need it.

+ +

You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with FilterableProductTable) or with the ones lower in it (ProductRow). In simpler examples, it's usually easier to go top-down, and on larger projects, it's easier to go bottom-up and write tests as you build.

+ +

At the end of this step, you'll have a library of reusable components that render your data model. The components will only have render() methods since this is a static version of your app. The component at the top of the hierarchy (FilterableProductTable) will take your data model as a prop. If you make a change to your underlying data model and call ReactDOM.render() again, the UI will be updated. It's easy to see how your UI is updated and where to make changes since there's nothing complicated going on. React's one-way data flow (also called one-way binding) keeps everything modular and fast.

+ +

Simply refer to the React docs if you need help executing this step.

+

A Brief Interlude: Props vs State #

+

There are two types of "model" data in React: props and state. It's important to understand the distinction between the two; skim the official React docs if you aren't sure what the difference is.

+

Step 3: Identify The Minimal (but complete) Representation Of UI State #

+

To make your UI interactive, you need to be able to trigger changes to your underlying data model. React makes this easy with state.

+ +

To build your app correctly, you first need to think of the minimal set of mutable state that your app needs. The key here is DRY: Don't Repeat Yourself. Figure out the absolute minimal representation of the state your application needs and compute everything else you need on-demand. For example, if you're building a TODO list, just keep an array of the TODO items around; don't keep a separate state variable for the count. Instead, when you want to render the TODO count, simply take the length of the TODO items array.

+ +

Think of all of the pieces of data in our example application. We have:

+ +
    +
  • The original list of products
  • +
  • The search text the user has entered
  • +
  • The value of the checkbox
  • +
  • The filtered list of products
  • +
+ +

Let's go through each one and figure out which one is state. Simply ask three questions about each piece of data:

+ +
    +
  1. Is it passed in from a parent via props? If so, it probably isn't state.
  2. +
  3. Does it remain unchanged over time? If so, it probably isn't state.
  4. +
  5. Can you compute it based on any other state or props in your component? If so, it isn't state.
  6. +
+ +

The original list of products is passed in as props, so that's not state. The search text and the checkbox seem to be state since they change over time and can't be computed from anything. And finally, the filtered list of products isn't state because it can be computed by combining the original list of products with the search text and value of the checkbox.

+ +

So finally, our state is:

+ +
    +
  • The search text the user has entered
  • +
  • The value of the checkbox
  • +
+

Step 4: Identify Where Your State Should Live #

+

See the Pen Thinking In React: Step 4 by Kevin Lacker (@lacker) on CodePen.

+ + + +

OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or owns, this state.

+ +

Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. This is often the most challenging part for newcomers to understand, so follow these steps to figure it out:

+ +

For each piece of state in your application:

+ +
    +
  • Identify every component that renders something based on that state.
  • +
  • Find a common owner component (a single component above all the components that need the state in the hierarchy).
  • +
  • Either the common owner or another component higher up in the hierarchy should own the state.
  • +
  • If you can't find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component.
  • +
+ +

Let's run through this strategy for our application:

+ +
    +
  • ProductTable needs to filter the product list based on state and SearchBar needs to display the search text and checked state.
  • +
  • The common owner component is FilterableProductTable.
  • +
  • It conceptually makes sense for the filter text and checked value to live in FilterableProductTable
  • +
+ +

Cool, so we've decided that our state lives in FilterableProductTable. First, add a getInitialState() method to FilterableProductTable that returns {filterText: '', inStockOnly: false} to reflect the initial state of your application. Then, pass filterText and inStockOnly to ProductTable and SearchBar as a prop. Finally, use these props to filter the rows in ProductTable and set the values of the form fields in SearchBar.

+ +

You can start seeing how your application will behave: set filterText to "ball" and refresh your app. You'll see that the data table is updated correctly.

+

Step 5: Add Inverse Data Flow #

+

See the Pen Thinking In React: Step 5 on CodePen.

+ + + +

So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in FilterableProductTable.

+ +

React makes this data flow explicit to make it easy to understand how your program works, but it does require a little more typing than traditional two-way data binding.

+ +

If you try to type or check the box in the current version of the example, you'll see that React ignores your input. This is intentional, as we've set the value prop of the input to always be equal to the state passed in from FilterableProductTable.

+ +

Let's think about what we want to happen. We want to make sure that whenever the user changes the form, we update the state to reflect the user input. Since components should only update their own state, FilterableProductTable will pass a callback to SearchBar that will fire whenever the state should be updated. We can use the onChange event on the inputs to be notified of it. And the callback passed by FilterableProductTable will call setState(), and the app will be updated.

+ +

Though this sounds complex, it's really just a few lines of code. And it's really explicit how your data is flowing throughout the app.

+

And That's It #

+

Hopefully, this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you're used to, remember that code is read far more than it's written, and it's extremely easy to read this modular, explicit code. As you start to build large libraries of components, you'll appreciate this explicitness and modularity, and with code reuse, your lines of code will start to shrink. :)

+ + +
+ + ← Prev + + +
+
+ - - - - + + + + - - - - - - - @@ -433,183 +466,57 @@
+ - -
- Edit on GitHub -

- Thinking in React -

-
- -

by Pete Hunt

- -

React is, in my opinion, the premier way to build big, fast Web apps with JavaScript. It has scaled very well for us at Facebook and Instagram.

- -

One of the many great parts of React is how it makes you think about apps as you build them. In this post, I'll walk you through the thought process of building a searchable product data table using React.

-

Start with a mock #

-

Imagine that we already have a JSON API and a mock from our designer. Our designer apparently isn't very good because the mock looks like this:

- -

Mockup

- -

Our JSON API returns some data that looks like this:

-
[
-  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
-  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
-  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
-  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
-  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
-  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
-];
-

Step 1: Break the UI into a component hierarchy #

-

The first thing you'll want to do is to draw boxes around every component (and subcomponent) in the mock and give them all names. If you're working with a designer, they may have already done this, so go talk to them! Their Photoshop layer names may end up being the names of your React components!

- -

But how do you know what should be its own component? Just use the same techniques for deciding if you should create a new function or object. One such technique is the single responsibility principle, that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents.

- -

Since you're often displaying a JSON data model to a user, you'll find that if your model was built correctly, your UI (and therefore your component structure) will map nicely. That's because UI and data models tend to adhere to the same information architecture, which means the work of separating your UI into components is often trivial. Just break it up into components that represent exactly one piece of your data model.

- -

Component diagram

- -

You'll see here that we have five components in our simple app. I've italicized the data each component represents.

- -
    -
  1. FilterableProductTable (orange): contains the entirety of the example
  2. -
  3. SearchBar (blue): receives all user input
  4. -
  5. ProductTable (green): displays and filters the data collection based on user input
  6. -
  7. ProductCategoryRow (turquoise): displays a heading for each category
  8. -
  9. ProductRow (red): displays a row for each product
  10. -
- -

If you look at ProductTable, you'll see that the table header (containing the "Name" and "Price" labels) isn't its own component. This is a matter of preference, and there's an argument to be made either way. For this example, I left it as part of ProductTable because it is part of rendering the data collection which is ProductTable's responsibility. However, if this header grows to be complex (i.e. if we were to add affordances for sorting), it would certainly make sense to make this its own ProductTableHeader component.

- -

Now that we've identified the components in our mock, let's arrange them into a hierarchy. This is easy. Components that appear within another component in the mock should appear as a child in the hierarchy:

- -
    -
  • FilterableProductTable - -
      -
    • SearchBar
    • -
    • ProductTable - -
        -
      • ProductCategoryRow
      • -
      • ProductRow
      • -
    • -
  • -
-

Step 2: Build a static version in React #

- - -

Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why.

- -

To build a static version of your app that renders your data model, you'll want to build components that reuse other components and pass data using props. props are a way of passing data from parent to child. If you're familiar with the concept of state, don't use state at all to build this static version. State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app, you don't need it.

- -

You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with FilterableProductTable) or with the ones lower in it (ProductRow). In simpler examples, it's usually easier to go top-down, and on larger projects, it's easier to go bottom-up and write tests as you build.

- -

At the end of this step, you'll have a library of reusable components that render your data model. The components will only have render() methods since this is a static version of your app. The component at the top of the hierarchy (FilterableProductTable) will take your data model as a prop. If you make a change to your underlying data model and call ReactDOM.render() again, the UI will be updated. It's easy to see how your UI is updated and where to make changes since there's nothing complicated going on. React's one-way data flow (also called one-way binding) keeps everything modular and fast.

- -

Simply refer to the React docs if you need help executing this step.

-

A brief interlude: props vs state #

-

There are two types of "model" data in React: props and state. It's important to understand the distinction between the two; skim the official React docs if you aren't sure what the difference is.

-

Step 3: Identify the minimal (but complete) representation of UI state #

-

To make your UI interactive, you need to be able to trigger changes to your underlying data model. React makes this easy with state.

- -

To build your app correctly, you first need to think of the minimal set of mutable state that your app needs. The key here is DRY: Don't Repeat Yourself. Figure out the absolute minimal representation of the state your application needs and compute everything else you need on-demand. For example, if you're building a TODO list, just keep an array of the TODO items around; don't keep a separate state variable for the count. Instead, when you want to render the TODO count, simply take the length of the TODO items array.

- -

Think of all of the pieces of data in our example application. We have:

- -
    -
  • The original list of products
  • -
  • The search text the user has entered
  • -
  • The value of the checkbox
  • -
  • The filtered list of products
  • -
- -

Let's go through each one and figure out which one is state. Simply ask three questions about each piece of data:

- -
    -
  1. Is it passed in from a parent via props? If so, it probably isn't state.
  2. -
  3. Does it remain unchanged over time? If so, it probably isn't state.
  4. -
  5. Can you compute it based on any other state or props in your component? If so, it isn't state.
  6. -
- -

The original list of products is passed in as props, so that's not state. The search text and the checkbox seem to be state since they change over time and can't be computed from anything. And finally, the filtered list of products isn't state because it can be computed by combining the original list of products with the search text and value of the checkbox.

- -

So finally, our state is:

- -
    -
  • The search text the user has entered
  • -
  • The value of the checkbox
  • -
-

Step 4: Identify where your state should live #

- - -

OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or owns, this state.

- -

Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. This is often the most challenging part for newcomers to understand, so follow these steps to figure it out:

- -

For each piece of state in your application:

- -
    -
  • Identify every component that renders something based on that state.
  • -
  • Find a common owner component (a single component above all the components that need the state in the hierarchy).
  • -
  • Either the common owner or another component higher up in the hierarchy should own the state.
  • -
  • If you can't find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component.
  • -
- -

Let's run through this strategy for our application:

- -
    -
  • ProductTable needs to filter the product list based on state and SearchBar needs to display the search text and checked state.
  • -
  • The common owner component is FilterableProductTable.
  • -
  • It conceptually makes sense for the filter text and checked value to live in FilterableProductTable
  • -
- -

Cool, so we've decided that our state lives in FilterableProductTable. First, add a getInitialState() method to FilterableProductTable that returns {filterText: '', inStockOnly: false} to reflect the initial state of your application. Then, pass filterText and inStockOnly to ProductTable and SearchBar as a prop. Finally, use these props to filter the rows in ProductTable and set the values of the form fields in SearchBar.

- -

You can start seeing how your application will behave: set filterText to "ball" and refresh your app. You'll see that the data table is updated correctly.

-

Step 5: Add inverse data flow #

- - -

So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in FilterableProductTable.

- -

React makes this data flow explicit to make it easy to understand how your program works, but it does require a little more typing than traditional two-way data binding.

- -

If you try to type or check the box in the current version of the example, you'll see that React ignores your input. This is intentional, as we've set the value prop of the input to always be equal to the state passed in from FilterableProductTable.

- -

Let's think about what we want to happen. We want to make sure that whenever the user changes the form, we update the state to reflect the user input. Since components should only update their own state, FilterableProductTable will pass a callback to SearchBar that will fire whenever the state should be updated. We can use the onChange event on the inputs to be notified of it. And the callback passed by FilterableProductTable will call setState(), and the app will be updated.

- -

Though this sounds complex, it's really just a few lines of code. And it's really explicit how your data is flowing throughout the app.

-

And that's it #

-

Hopefully, this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you're used to, remember that code is read far more than it's written, and it's extremely easy to read this modular, explicit code. As you start to build large libraries of components, you'll appreciate this explicitness and modularity, and with code reuse, your lines of code will start to shrink. :)

- - -
- - ← Prev - - - Next → - -
-
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
- -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Integrazione con Strumenti -

-
- -

Ciascun progetto utilizza un sistema differente per la build e il deploy di JavaScript. Abbiamo provato a rendere React il più possibile indipendente dall'ambiente di sviluppo.

-

React #

React hosted su un CDN #

-

Offriamo versioni di React su CDN nella nostra pagina dei download. Questi file precompilati usano il formato dei moduli UMD. Inserirli con un semplice tag <script> inietterà una variabile globale React nel tuo ambiente. Questo approccio dovrebbe funzionare senza alcuna configurazione in ambienti CommonJS ed AMD.

-

Usare il ramo master #

-

Abbiamo istruzioni per compilare dal ramo master nel nostro repositorio GitHub. Costruiamo un albero di moduli CommonJS sotto build/modules che puoi inserire in ogni ambiente o strumento di packaging che supporta CommonJS.

-

JSX #

Trasformazione di JSX nel browser #

-

Se preferisci usare JSX, Babel fornisce un trasformatore ES6 e JSX nel browser per lo sviluppo chiamato browser.js che può essere incluso da una release npm babel-core oppure da CDNJS. Includi un tag <script type="text/babel"> per scatenare il trasformatore JSX.

- -
-

Nota:

- -

Il trasformatore JSX nel browser è piuttosto grande e risulta in calcoli aggiuntivi lato client che possono essere evitati. Non utilizzare in produzione — vedi la sezione successiva.

-
-

In Produzione: JSX Precompilato #

-

Se hai npm, puoi eseguire npm install -g babel. Babel include il supporto per React v0.12 e v0.13. I tag sono automaticamente trasformati negli equivalenti React.createElement(...), displayName è automaticamente desunto e aggiunto a tutte le classi React.createClass.

- -

Questo strumento tradurrà i file che usano la sintassi JSX a file in semplice JavaScript che possono essere eseguiti direttamente dal browser. Inoltre, osserverà le directory per te e trasformerà automaticamente i file quando vengono modificati; ad esempio: babel --watch src/ --out-dir lib/.

- -

In maniera predefinita, vengono trasformati i file JSX con un'estensione .js. Esegui babel --help per maggiori informazioni su come usare Babel.

- -

Output di esempio:

-
$ cat test.jsx
-var HelloMessage = React.createClass({
-  render: function() {
-    return <div>Ciao {this.props.name}</div>;
-  }
-});
-
-ReactDOM.render(<HelloMessage name="John" />, mountNode);
-$ babel test.jsx
-"use strict";
-
-var HelloMessage = React.createClass({
-  displayName: "HelloMessage",
-
-  render: function render() {
-    return React.createElement(
-      "div",
-      null,
-      "Hello ",
-      this.props.name
-    );
-  }
-});
-
-ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
-

Progetti Open Source Utili #

-

La comunità open source ha creato strumenti che integrano JSX con diversi editor e sistemi di build. Consulta integrazioni JSX per una lista completa.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tooling-integration-ja-JP.html b/docs/tooling-integration-ja-JP.html deleted file mode 100644 index 7dcf4d2068..0000000000 --- a/docs/tooling-integration-ja-JP.html +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - - インテグレーションツール | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- インテグレーションツール -

-
- -

全てのプロジェクトがJavaScriptをビルドしたりデプロイするのに様々なシステムを使用しています。私たちはReactをできるだけ環境不問にしようとしています。

-

React #

CDNにホストされたReact #

-

ダウンロードページでCDNにホストされたバージョンのReactが提供されています。それらの、事前にビルドされたファイルはUMDモジュールフォーマットを使用しています。簡単な <script> タグを使ってそれらを導入することで、あなたの環境でグローバルに React を使うことができます。CommonJSの外や、AMDの環境でも、それは動作するでしょう。

-

masterを使う #

-

GitHubリポジトリに master からビルドする説明が書いてあります。build/modules の下にCommonJSモジュールのツリーをビルドします。それらは、どんな環境やCommonJSがサポートされているパッケージングツールでも導入できます。

-

JSX #

ブラウザ上でのJSXの変換 #

-

JSXを使用したい場合、ダウンロードページに開発のためにブラウザ上でのJSXトランスフォーマーを提供しています。単純に <script type="text/jsx"> をインクルードすることでJSXトランスフォーマーを使用できます。

- -
-

注意: -ブラウザ上でのJSXトランスフォーマーをとても大きく、避けることのできるクライアントサイドの計算になりかねません。プロダクションでは使わないでください。詳細は次のセクションをご覧ください。

-
-

プロダクションで使う場合:事前にコンパイルされたJSX #

-

npmがインストールされている場合、コマンドラインの jsx ツールは単純に npm install -g react-tools コマンドを流せばインストールできます。このツールはJSXを使用しているファイルを直接ブラウザ上で動く生のJavaScriptファイルに変換します。また、ディレクトリをウォッチして、ファイルが変更されたら自動的に変換を行います。例えば、次のようなコマンドで。 jsx --watch src/ build/

- -

デフォルトで、拡張子が .js のJSXファイルは変換されます。拡張子が .jsx のファイルを変換するには jsx --extension jsx src/ build/ コマンドを使用してください。

- -

このツールの使用方法についての詳細の情報については、 jsx --help コマンドを使用してください。

-

役に立つオープンソースのプロジェクト #

-

オープンソースコミュニティがJSXをいくつかのエディタやビルドシステムで使用するためのツールを作成しました。一覧はJSXのインテグレーションを参照してください。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tooling-integration-ko-KR.html b/docs/tooling-integration-ko-KR.html deleted file mode 100644 index e92014852a..0000000000 --- a/docs/tooling-integration-ko-KR.html +++ /dev/null @@ -1,550 +0,0 @@ - - - - - - - 툴 통합 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 툴 통합 -

-
- -

모든 프로젝트는 JavaScript를 빌드, 배포할 때 다른 시스템을 사용합니다. 우리는 가능한 한 React를 환경에 구속받지 않도록 하려 노력했습니다.

-

React #

CDN-호스트 React #

-

다운로드 페이지에서 React의 CDN 호스트 버전을 제공합니다. 이 미리 빌드된 파일들은 UMD 모듈 포맷을 사용합니다. 간단한 <script> 태그로 넣어보면 React 글로벌이 환경으로 주입(inject)될 것입니다. CommonJS와 AMD환경에서 별도의 작업 없이도 동작해야 합니다.

-

master 사용하기 #

-

GitHub 저장소master에 빌드 방법이 있습니다. 이는 build/modules에 CommonJS 모듈 트리를 빌드합니다. 이는 CommonJS를 지원하는 어떤 환경이나 패키징 툴에도 넣을 수 있습니다.

-

JSX #

브라우저에서 JSX 변환 #

-

JSX를 사용하신다면, Babel에서 browser.js라는 개발용 브라우저 ES6, JSX 변환기를 제공합니다. 이는 babel-core의 npm 릴리스나 CDNJS로 넣을 수 있습니다. <script type="text/babel">를 넣으면 JSX 변환기가 작동합니다.

- -
-

주의:

- -

브라우저 JSX 변환기는 꽤 크고 안 할 수도 있는 클라이언트 측 연산을 하게 됩니다. 프로덕션 환경에서 사용하지 마시고, 다음 단락을 보세요.

-
-

상용화하기: 미리 컴파일된 JSX #

-

npm 모듈을 가지고 있다면, npm install -g babel-cli를 실행할 수 있습니다. Babel은 React v0.12이상을 내장 지원합니다. 태그는 자동적으로 동등한 React.createElement(...)로 변환되며, displayName은 모든 React.createClass 호출에 자동으로 추론, 추가됩니다.

- -

이 툴은 JSX 구문을 일반적인 JavaScript파일로 변환해 브라우져에서 바로 실행할 수 있도록 합니다. 디렉터리를 감시해 파일이 변경되었을 때 자동으로 변환하도록 할 수도 있습니다. 예를 들면 babel --watch src/ --out-dir lib/ 이렇게요.

- -

Babel 6부터 기본값으로 변환기가 포함되지 않게 되었습니다. 이는 babel 명령을 실행할 때나 .babelrc에 반드시 옵션을 지정해야 한다는 뜻입니다. React를 사용할 때 가장 일반적인 방법은 es2015, react 프리셋을 사용하는 것입니다. Babel의 변경에 대한 좀 더 자세한 정보는 블로그에 올라온 Babel 6 공지 글을 읽어보세요.

- -

ES2015 문법과 React를 사용하려 할 경우의 예제입니다.

-
npm install babel-preset-es2015 babel-preset-react
-babel --presets es2015,react --watch src/ --out-dir lib/
-
-

기본적으로는 JSX 파일들은 .js 확장자로 변환됩니다. 바벨을 어떻게 사용하는지 더 자세하게 알고싶으시면 babel --help를 실행해 보세요.

- -

출력 예:

-
$ cat test.jsx
-var HelloMessage = React.createClass({
-  render: function() {
-    return <div>Hello {this.props.name}</div>;
-  }
-});
-
-ReactDOM.render(<HelloMessage name="John" />, mountNode);
-$ babel test.jsx
-"use strict";
-var HelloMessage = React.createClass({
-  displayName: "HelloMessage",
-  render: function render() {
-    return React.createElement(
-      "div",
-      null,
-      "Hello ",
-      this.props.name
-    );
-  }
-});
-
-ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
-

도움되는 오픈소스 프로젝트들 #

-

오픈 소스 커뮤니티는 JSX와 연동하는 여러 에디터와 빌드 시스템을 만들었습니다. 전 목록은 JSX 연동에서 보세요.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tooling-integration-zh-CN.html b/docs/tooling-integration-zh-CN.html deleted file mode 100644 index 9b6391e636..0000000000 --- a/docs/tooling-integration-zh-CN.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - 工具集成 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 工具集成 -

-
- -

我们尽可能使 React 与环境无关。大家可以在各种语言(JavaScript, TypeScript, ClojureScript, etc)与各种环境(web, iOS, Android, NodeJS, Nashorn, etc)中使用 React。这里有很多工具来帮助你创建优秀的应用。在这一节中我们介绍一些在 React 中最流行的工具。

- -
    -
  • 语言工具 描述如何设置例如 Babel 的工具来编译 JSX。
  • -
  • 包管理 讲述如何设置将 React 配置为项目中的依赖。
  • -
  • 服务端环境 讲述如何为 React 配置服务端渲染环境。
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tooling-integration.html b/docs/tooling-integration.html deleted file mode 100644 index ea8be6590e..0000000000 --- a/docs/tooling-integration.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - Tooling Integration | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Tooling Integration -

-
- -

We've tried to make React as environment-agnostic as possible. People use React in a variety of languages (JavaScript, TypeScript, ClojureScript, etc) and in a variety of environments (web, iOS, Android, NodeJS, Nashorn, etc). There are many tools to help you build great applications. In these sections we introduce some of the tools that are most commonly used together with React.

- -
    -
  • Language Tooling describes how to set up tools like Babel to transpile JSX for a better development experience.
  • -
  • Package Management describes how to configure React as a dependency of your project.
  • -
  • Server-side Environments describes how to configure your environment for server-side rendering with React.
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/top-level-api-it-IT.html b/docs/top-level-api-it-IT.html deleted file mode 100644 index 3a38aecf14..0000000000 --- a/docs/top-level-api-it-IT.html +++ /dev/null @@ -1,592 +0,0 @@ - - - - - - - API di Livello Elevato | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- API di Livello Elevato -

-
- -

React #

-

React è il punto di ingresso alla libreria React. Se stai usando uno dei pacchetti precompilati, è disponibile come variabile globale; se stai usando i moduli CommonJS puoi richiederlo con require().

-

React.Component #

class Component
-
-

Questa è la classe base per i componenti React quando sono definiti usando le classi ES6. Vedi Componenti Riutilizzabili per usare le classi ES6 con React. Per i metodi forniti dalla classe base, vedi la API dei Componenti.

-

React.createClass #

ReactClass createClass(object specification)
-
-

Crea la classe di un componente, data una specifica. Un componente implementa un metodo render che restituisce un singolo figlio. Tale figlio può avere una struttura di fogli arbitrariamente profonda. Una cosa che rende i componenti diversi dalle classi prototipiche standard è che non hai bisogno di chiamare new su di esse. Sono delle convenienti astrazioni che costruiscono (attraverso new) istanze dietro le quinte per te.

- -

Per maggiori informazioni sull'oggetto specifica, vedi Specifiche dei Componenti e Ciclo di Vita.

-

React.createElement #

ReactElement createElement(
-  string/ReactClass type,
-  [object props],
-  [children ...]
-)
-
-

Crea e restituisce un nuovo ReactElement del tipo desiderato. L'argomento type può essere una stringa contenente il nome di un tag HTML (ad es. 'div', 'span', etc), oppure una ReactClass (creata attraverso React.createClass).

-

React.cloneElement #

ReactElement cloneElement(
-  ReactElement element,
-  [object props],
-  [children ...]
-)
-
-

Clona e restituisce un nuovo ReactElement usando element come punto di partenza. L'elemento risultante avrà le proprietà dell'elemento originale, con le nuove proprietà unite in maniera superficiale. I figli esistenti sono sostituiti dai figli passati come children. Diversamente da React.addons.cloneWithProps, key e ref dell'elemento originale saranno preservati. Non esiste alcun comportamento speciale per riunire le proprietà (diversamente da cloneWithProps). Vedi l'articolo del blog sulla v0.13 RC2 per maggiori dettagli.

-

React.createFactory #

factoryFunction createFactory(
-  string/ReactClass type
-)
-
-

Restituisce una funzione che produce ReactElements di un tipo desiderato. Come React.createElement, -l'argomento type può essere sia la stringa contenente il nome di un tag HTML (ad es. 'div', 'span', etc), oppure una -ReactClass.

-

ReactDOM.render #

ReactComponent render(
-  ReactElement element,
-  DOMElement container,
-  [function callback]
-)
-
-

Effettua il rendering di un ReactElement nel DOM all'interno dell'elemento container fornito e restituisce un riferimento al componente (oppure restituisce null per i componenti privi di stato).

- -

Se il rendering del ReactElement è stato precedentemente effettuato all'interno di container, questa operazione effettuerà un aggiornamento su di esso e modificherà il DOM in modo necessario a riflettere il più recente componente React.

- -

Se la callback opzionale è fornita, sarà eseguita dopo che il rendering o l'aggiornamento del componente sono stati effettuati.

- -
-

Nota:

- -

ReactDOM.render() controlla i contenuti del nodo contenitore che viene passato come argomento container. Gli elementi DOM -esistenti al suo interno sono sostituiti quando viene chiamata la prima volta. Le chiamate successive usano l'algoritmo di -differenza di React per aggiornamenti efficienti.

- -

ReactDOM.render() non modifica il nodo contenitore (modifica soltanto i figli del contenitore). In -futuro potrebbe essere possibile inserire un componente in un nodo DOM esistente senza sovrascrivere i figli esistenti.

-
-

ReactDOM.unmountComponentAtNode #

boolean unmountComponentAtNode(DOMElement container)
-
-

Rimuove un componente React montato nel DOM e ripulisce i suoi gestori di evento e lo stato. Se nessun componente è stato montato nel contenitore container, chiamare questa funzione non ha alcun effetto. Restituisce true se il componente è stato smontato e false se non è stato trovato un componente da smontare.

-

ReactDOM.renderToString #

string renderToString(ReactElement element)
-
-

Effettua il rendering di un ReactElement come il suo HTML iniziale. Questo dovrebe essere utilizzato soltanto lato server. React restituirà una stringa di HTML. Puoi usare questo metodo per generare HTML sul server e inviare il markup come risposta alla richiesta iniziale per un più rapido caricamento della pagina, e permettere ai motori di ricerca di effettuare il crawling della tua pagina per ottimizzazione SEO.

- -

Se chiami ReactDOM.render() su un nodo che possiede già questo markup generato lato server, React lo preserverà e vi attaccherà soltanto i gestori di eventi, permettendoti di avere una esperienza di primo caricamento altamente efficiente.

-

ReactDOM.renderToStaticMarkup #

string renderToStaticMarkup(ReactElement element)
-
-

Simile a renderToString, eccetto che non crea attributi DOM aggiuntivi come data-react-id, che React utilizza internamente. Questo è utile se vuoi usare React come un semplice generatore di pagine statiche, in quanto eliminare gli attributi aggiuntivi può risparmiare parecchi byte.

-

ReactDOM.isValidElement #

boolean isValidElement(* object)
-
-

Verifica che object sia un ReactElement.

-

ReactDOM.findDOMNode #

DOMElement findDOMNode(ReactComponent component)
-
-

Se questo componente è stato montato nel DOM, restituisce il corrispondente elemento DOM nativo del browser. Questo metodo è utile per leggere i valori dal DOM, come i valori dei campi dei moduli ed effettuare misure sul DOM. Quando render restituisce null o false, findDOMNode restituisce null.

- -
-

Nota:

- -

findDOMNode() è una via di fuga usata per accedere al nodo DOM sottostante. Nella maggior parte dei casi, l'uso di questa via di fuga è scoraggiato perché viola l'astrazione del componente. Tuttavia, esistono delle situazioni in cui questo è necessario (ad esempio, potresti aver bisogno di trovare un nodo DOM per posizionarlo in maniera assoluta oppure determinarne la larghezza visualizzata misurata in pixel).

- -

findDOMNode() funziona soltanto su componenti montati (cioè, componenti che sono stati posizionati nel DOM). Se provi a chiamarlo su un componente che non è stato ancora montato (come chiamare findDOMNode() in render() su un componente che deve ancora essere creato) lancerà un'eccezione.

-
-

React.DOM #

-

React.DOM fornisce convenienti utilità che espongono React.createElement per componenti del DOM. Questi dovrebbero essere usate soltanto quando non si utilizza JSX. Ad esempio, React.DOM.div(null, 'Ciao Mondo!')

-

React.PropTypes #

-

React.PropTypes include tipi che possono essere usati con l'oggetto propTypes di un componente per validare le proprietà passate ai tuoi componenti. Per maggiori informazioni su propTypes, vedi Componenti Riutilizzabili.

-

React.Children #

-

React.Children fornisce utilitià per gestire la struttura dati opaca this.props.children.

-

React.Children.map #

object React.Children.map(object children, function fn [, object thisArg])
-
-

Invoca fn su ciascuno dei diretti discendenti contenuti in children, con this impostato a thisArg. Se children è un oggetto annidato o un array, esso verrà attraversato: ad fn non saranno mai passati gli oggetti contenitori. Se children è null o undefined restituisce null o undefined anziché un oggetto vuoto.

-

React.Children.forEach #

React.Children.forEach(object children, function fn [, object thisArg])
-
-

Come React.Children.map() con la differenza che non restituisce un oggetto.

-

React.Children.count #

number React.Children.count(object children)
-
-

Restituisce il numero totale di componenti in children, uguale al numero di volte che una callback passata a map o forEach verrebbe invocata.

-

React.Children.only #

object React.Children.only(object children)
-
-

Restituisce il figlio unico contenuto in children, altrimenti lancia un'eccezione.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/top-level-api-ja-JP.html b/docs/top-level-api-ja-JP.html deleted file mode 100644 index 9be645dff6..0000000000 --- a/docs/top-level-api-ja-JP.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - - Top-Level API | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Top-Level API -

-
- -

React #

-

React はReactのライブラリに対するエントリーポイントです。事前にビルドされたパッケージを使用する場合は、グローバルで使用可能です。CommonJSのモジュールを使用する場合は、 require() できます。

-

React.Component #

class Component
-
-

これは、ES6のクラスを使用して定義されている場合の、Reactコンポーネントに対する基底クラスです。ReactでES6のクラスを使用する方法については、再利用可能なコンポーネントをご覧ください。基底クラスからどのメソッドが実際に提供されるかについては、コンポーネントAPIをご覧ください。

-

React.createClass #

ReactClass createClass(object specification)
-
-

与えられた仕様に基づいてコンポーネントクラスを作成します。コンポーネントは ある単一の 子要素を返す render メソッドを実行します。その子要素は勝手に深い子要素の構造を保持しています。コンポーネントが標準的なプロトタイプのクラスと異なっている部分は、newを呼ぶ必要がないということです。それらは内部で(newを行う)インスタンスを構築する便利なラッパーです。

- -

specificationオブジェクトについての情報は、コンポーネントのスペックとライフサイクルをご覧ください。

-

React.createElement #

ReactElement createElement(
-  string/ReactClass type,
-  [object props],
-  [children ...]
-)
-
-

与えられた型の ReactElement を作成し、返します。type引数はhtmlタグ名(例えば、'div'、'span'など)の文字列にもReactClassReact.createClass によって作成される)にもなり得ます。

-

React.cloneElement #

ReactElement cloneElement(
-  ReactElement element,
-  [object props],
-  [children ...]
-)
-
-

element をスターティングポイントとして使用する新しい ReactElement をクローンして返します。 -結果として生まれる要素はオリジナルの要素のpropsと新しいpropsを暗にマージしたものを保持しています。新しい子要素は現存する子要素を置き換えます。 React.addons.cloneWithProps と異なり、オリジナルの要素から得られた keyref は保存されます。(cloneWithProps とは異なり)propsをマージする際に特別な動きは行いません。詳細については、v0.13 RC2 blog記事をご覧ください。

-

React.createFactory #

factoryFunction createFactory(
-  string/ReactClass type
-)
-
-

与えられた型のReactElementsを生成する関数を返します。 React.createElement と同様に、type引数はhtmlタグ名(例えば、'div'、'span'など)の文字列にもReactClass にもなり得ます。

-

React.render #

ReactComponent render(
-  ReactElement element,
-  DOMElement container,
-  [function callback]
-)
-
-

与えられた container によってReactElementをDOMにレンダリングし、コンポーネントへの参照を返します。

- -

もしReactElementが事前に container にレンダリングされていた場合は、更新を行い、DOMが最新のReactのコンポーネントを表すように変化させます。

- -

オプションのコールバックが与えられた場合は、コンポーネントがレンダリングされたり、更新された後に実行されます。

- -
-

注意: -React.render() は渡されたコンテナーノードの内容を制御します。内部に存在するDOM要素は最初に呼ばれた際に置き換えられます。その後に呼ばれた場合は、ReactのDOMの差分アルゴリズムを使用して、効率的に更新されます。

- -

React.render() はコンテナーノードの変更は行いません(コンテナの子要素のみ変更を行います)。今後、存在する子要素を上書きすることなく、存在するDOMノードにコンポーネントを挿入することが可能になるでしょう。

-
-

React.unmountComponentAtNode #

boolean unmountComponentAtNode(DOMElement container)
-
-

マウントされたReactのコンポーネントをDOMから削除し、そのイベントハンドラとstateをクリーンアップします。コンテナにコンポーネントがマウントされていない場合は、この関数を呼んでも何も行われません。コンポーネントがアンマウントされた場合は true を返し、アンマウントするコンポーネントが存在しない場合は false を返します。

-

React.renderToString #

string renderToString(ReactElement element)
-
-

ReactElementを最初にHTMLにレンダリングします。これはサーバでのみ使用されるべきです。ReactはHTML文字列を返します。このメソッドを、サーバでHTMLを生成し、最初のリクエストに対してマークアップを送るのに使用することができます。そうすることで、ページロードが速くなり、サーチエンジンはSEOの目的でページをクロールします。

- -

既にサーバでレンダリングされたマークアップを保持しているノードで React.render() を呼んだ場合は、Reactはそれを保護し、イベントハンドラを加えます。そうすることで、最初のローディングのパフォーマンスがとても良くなります。

-

React.renderToStaticMarkup #

string renderToStaticMarkup(ReactElement element)
-
-

renderToString に似ていますが、Reactが内部で使用する data-react-id のような外部のDOM属性を作成しません。Reactを、単純な静的なページを生成するために使用したい場合は有用です。外部の属性を取り除くことでメモリを節約することができます。

-

React.isValidElement #

boolean isValidElement(* object)
-
-

オブジェクトがReactElementであるかどうか調査します。

-

React.findDOMNode #

DOMElement findDOMNode(ReactComponent component)
-
-

このコンポーネントがDOMにマウントされた場合は、対応するネイティブブラウザのDOM要素を返します。このメソッドはDOMの外の値を読み込む場合に有用です。例えば、formフィールドの値やDOMの測定を行う場合があります。 rendernullfalse を返した場合は、 findDOMNodenull を返します。

-

React.DOM #

-

React.DOM はDOMコンポーネントのための React.createElement の周りの便利なラッパーを提供します。JSXを使用しない場合にのみ使用すべきです。例えば、 React.DOM.div(null, 'Hello World!') のように。

-

React.PropTypes #

-

React.PropTypes はコンポーネントに与えられたpropsをバリデーションするためにコンポーネントの propTypes と使用できる型を含んでいます。 propTypes についての更なる情報は、再利用可能なコンポーネントをご覧ください。

-

React.Children #

-

React.Childrenthis.props.children の不透明なデータ構造を扱うユーティリティを提供します。

-

React.Children.map #

object React.Children.map(object children, function fn [, object thisArg])
-
-

全ての children を含む子要素に対して、 fn を実行します。 thisthisArg にセットされます。 children がネストしたオブジェクトや配列だった場合は、実行されません。 fn はコンテナのオブジェクトから渡されません。子要素が nullundefined だった場合は、空のオブジェクトではなく nullundefined を返します。

-

React.Children.forEach #

React.Children.forEach(object children, function fn [, object thisArg])
-
-

React.Children.map() に似ていますが、オブジェクトを返しはしません。

-

React.Children.count #

number React.Children.count(object children)
-
-

children の中のコンポーネントの合計数を返します。 mapforEach に渡されるコールバックが実行される数と等しくなります。

-

React.Children.only #

object React.Children.only(object children)
-
-

children の単一の子要素を返します。それ以外の場合は例外をスローします。

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/top-level-api-ko-KR.html b/docs/top-level-api-ko-KR.html deleted file mode 100644 index 028b80de39..0000000000 --- a/docs/top-level-api-ko-KR.html +++ /dev/null @@ -1,596 +0,0 @@ - - - - - - - 최상위 API | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 최상위 API -

-
- -

React #

-

React는 React 라이브러리의 진입점입니다. 미리 빌드된 패키지를 사용하는 경우 전역 변수로 접근할 수 있습니다. CommonJS 모듈을 사용하는 경우에는 require()로 불러올 수 있습니다.

-

React.Component #

class Component
-
-

ES6 클래스 구문을 사용해 React 컴포넌트를 정의했을 때 기본 클래스가 되는 부분입니다. 어떻게 ES6 클래스 구문을 사용해 React를 다루는지는 재사용가능한 컴포넌트를 확인하세요. 기본 클래스에서 실제 제공되는 메소드들에는 어떤것이 있는지 알아보려면 컴포넌트 API를 확인하세요.

-

React.createClass #

ReactClass createClass(object specification)
-
-

주어진 명세에 따라 컴포넌트 클래스를 만듭니다. 컴포넌트는 단 하나의 자식만을 리턴하는 render 메소드를 구현합니다. 그 자식은 임의 깊이의 자식 구조를 가질 수 있습니다. 컴포넌트가 일반적인 프로토타입 기반의 클래스와 다른 점은 생성할 때 new 연산자를 사용하지 않아도 된다는 것입니다. 컴포넌트는 (new 연산자를 통해) 내부 인스턴스를 만들어 주는 편의 래퍼(wrapper)입니다.

- -

명세 객체에 대한 자세한 정보는 컴포넌트 명세와 생명주기를 참고하세요.

-

React.createElement #

ReactElement createElement(
-  string/ReactClass type,
-  [object props],
-  [children ...]
-)
-
-

주어진 타입의 새 ReactElement를 만들고 리턴합니다. type 인자는 HTML 태그명 문자열 (예: 'div', 'span' 등) 또는 (React.createClass로 만든) ReactClass입니다.

-

React.cloneElement #

ReactElement cloneElement(
-  ReactElement element,
-  [object props],
-  [children ...]
-)
-
-

element를 시작점으로 새로운 ReactElement를 클론해 반환합니다. 반환된 엘리먼트에는 원본의 props와 새로운 props가 얕게 병합됩니다. 새 자식은 존재하는 자식을 교체할 것입니다. React.addons.cloneWithProps와는 다르게, 원본 엘리먼트의 keyref는 보존될 것입니다. cloneWithProps와는 달리 props이 병합되는데는 어떠한 특별한 동작도 없습니다. v0.13 RC2 블로그 포스트에서 추가적인 내용을 확인하세요.

-

React.createFactory #

factoryFunction createFactory(
-  string/ReactClass type
-)
-
-

주어진 타입의 ReactElement를 만들어주는 함수를 리턴합니다. React.createElement와 마찬가지로 type 인자는 HTML 태그명 문자열 (예: 'div', 'span' 등) 또는 ReactClass입니다.

-

React.isValidElement #

boolean isValidElement(* object)
-
-

주어진 객체가 ReactElement인지 확인합니다.

-

React.DOM #

-

React.DOM은 DOM 컴포넌트에 대해 React.createElement의 편의 래퍼(wrapper)를 제공합니다. JSX를 사용하지 않는 경우에만 사용하십시오. 예를 들어, React.DOM.div(null, 'Hello World!')와 같이 사용할 수 있습니다.

-

React.PropTypes #

-

React.PropTypes는 컴포넌트에 넘어오는 props가 올바른지 검사할 수 있는 컴포넌트의 propTypes 객체에 들어가는 타입을 가집니다. propTypes에 대한 자세한 정보는 재사용 가능한 컴포넌트를 참고하세요.

-

React.Children #

-

React.Children은 불투명한 자료 구조인 this.props.children를 다룰 수 있는 유틸리티를 제공합니다.

-

React.Children.map #

array React.Children.map(object children, function fn [, object thisArg])
-
-

children의 바로 밑에 있는 모든 자식에 fn을 호출합니다. 이 때 thisthisArg로 설정됩니다. children이 중첩된 객체나 배열일 경우 그 안의 값을 순회합니다. 따라서 fn에 컨테이너 객체가 넘어가는 일은 일어나지 않습니다. childrennull이거나 undefined면 배열 대신 null 또는 undefined를 리턴합니다.

-

React.Children.forEach #

React.Children.forEach(object children, function fn [, object thisArg])
-
-

React.Children.map()과 비슷하지만 배열을 리턴하지 않습니다.

-

React.Children.count #

number React.Children.count(object children)
-
-

children에 들어있는 컴포넌트의 총 갯수를 리턴합니다. 이 갯수는 map이나 forEach에 넘긴 콜백이 호출되는 횟수와 동일합니다.

-

React.Children.only #

object React.Children.only(object children)
-
-

children에 단 하나의 자식이 있을 때 그 자식을 리턴합니다. 그 밖의 경우에는 예외를 발생시킵니다.

-

React.Children.toArray #

array React.Children.toArray(object children)
-
-

불투명한 자료구조인 children를 개별 자식마다 키를 할당해 평면 배열로 리턴합니다. 이는 render 메소드 내에서 자식의 컬렉션을 조작할 때, 특히 this.props.children을 넘기기 전에 재정렬하거나 재단할 때 유용합니다.

-

ReactDOM #

-

react-dom 패키지는 앱의 최상위 레벨에서 사용될 DOM 고유의 메소드를 제공하며, 원한다면 리액트 외부모델을 위한 출구로 사용될 수 있습니다. 대부분의 컴포넌트는 이 모듈을 사용할 필요가 없습니다.

-

ReactDOM.render #

ReactComponent render(
-  ReactElement element,
-  DOMElement container,
-  [function callback]
-)
-
-

주어진 ReactElement를 container 인자에 넘어온 DOM 안에 렌더링하고 컴포넌트의 레퍼런스를 컴포넌트에 리턴합니다. 상태가 없는 컴포넌트에서는 null을 리턴합니다.

- -

어떤 ReactElement가 이미 container에 렌더링 된 적이 있다면, 그것을 업데이트한 뒤 React 컴포넌트의 최신 상태를 반영하기 위해 꼭 필요한 만큼만 DOM을 변경합니다.

- -

콜백 인자를 넘기면 컴포넌트가 렌더링되거나 업데이트 된 다음 호출됩니다.

- -
-

주의:

- -

ReactDOM.render()는 넘어온 컨테이너 노드의 내용을 교체합니다. 안에 있는 DOM 엘리먼트는 첫 호출을 할 때 교체됩니다. 그 후의 호출에는 효율석으로 업데이트하기 위해 React의 DOM diff 알고리즘을 사용합니다.

- -

ReactDOM.render()는 컨테이너 노드를 수정하지 않습니다. (컨테이너의 자식만 수정함) 추후에 기존 자식들을 덮어쓰지 않고 이미 있는 DOM 노드에 컴포넌트를 삽입하는 것도 지원할 가능성이 있습니다.

-
-

ReactDOM.unmountComponentAtNode #

boolean unmountComponentAtNode(DOMElement container)
-
-

DOM에 마운트된 React 컴포넌트를 제거하고 이벤트 핸들러 및 state를 정리합니다. 컨테이너에 마운트된 컴포넌트가 없는 경우에는 호출해도 아무 동작을 하지 않습니다. 컴포넌트가 마운트 해제된 경우 true를, 마운트 해제할 컴포넌트가 없으면 false를 리턴합니다.

-

ReactDOM.findDOMNode #

DOMElement findDOMNode(ReactComponent component)
-
-

이 컴포넌트가 DOM에 마운트된 경우 해당하는 네이티브 브라우저 DOM 엘리먼트를 리턴합니다. 이 메소드는 폼 필드의 값이나 DOM의 크기/위치 등 DOM에서 정보를 읽을 때 유용합니다. 대부분의 경우, DOM 노드에 ref를 쓸 수 있으며 findDOMNode를 사욯할 필요는 없습니다. rendernull이나 false를 리턴할 때 findDOMNode()null을 리턴합니다.

- -
-

주의:

- -

findDOMNode()는 기본 DOM 노드에 접근하기 위한 출구입니다. 컴포넌트 추상화를 파괴하기 때문에 대부분의 경우 이것의 사용은 권장되지 않습니다.

- -

findDOMNode()는 마운트된 컴포넌트에서만 작동합니다. 이는 컴포넌트가 DOM에 위치해야 함을 뜻합니다. 만약 아직 생성되기전의 컴포넌트에서 render()에서 findDOMNode()를 호출하는 등 컴포넌트가 마운트 되기 이전에 이를 호출한다면, 예외가 던져질 것입니다.

- -

findDOMNode()는 상태가없는 컴포넌트에서 쓸 수 없습니다.

-
-

ReactDOMServer #

-

react-dom/server 패키지는 서버단에서 컴포넌트를 렌더할 수 있도록 해 줍니다.

-

ReactDOMServer.renderToString #

string renderToString(ReactElement element)
-
-

주어진 ReactElement의 최초 HTML을 렌더링합니다. 이 함수는 서버에서만 사용해야 합니다. React가 HTML 문자열을 리턴합니다. HTML을 서버에서 생성하고 마크업을 최초 요청에 내려보내서, 페이지 로딩을 빠르게 하거나 검색 엔진이 크롤링할 수 있도록 하는 SEO 목적으로 이 메소드를 사용할 수 있습니다.

- -

또한 이 메소드로 서버에서 렌더링한 마크업을 포함한 노드에 ReactDOM.render()를 호출하면, React는 마크업을 보존하고 이벤트 핸들러만 붙이므로 최초 로딩을 매우 빠르게 느껴지게 할 수 있습니다.

-

ReactDOMServer.renderToStaticMarkup #

string renderToStaticMarkup(ReactElement element)
-
-

renderToString와 비슷하지만 data-react-id처럼 React에서 내부적으로 사용하는 추가적인 DOM 어트리뷰트를 만들지 않습니다. 추가적인 어트리뷰트를 제거하면 생성되는 마크업의 용량을 줄일 수 있기 때문에 React를 단순한 정적 페이지 생성기로 사용할 때 유용합니다.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/top-level-api-zh-CN.html b/docs/top-level-api-zh-CN.html deleted file mode 100644 index e2b8849fab..0000000000 --- a/docs/top-level-api-zh-CN.html +++ /dev/null @@ -1,600 +0,0 @@ - - - - - - - Top-Level API | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Top-Level API -

-
- -

React #

-

React 是 React 库的入口点。如果你使用预编译包中的一个,则 React 为全局变量;如果你使用 CommonJS 模块,你可以 require() 它。

-

React.Component #

class Component
-
-

当使用ES6 类定义时,React.Component是 React 组件的基类。如何在React中使用 ES6 class 请参见 可重用组件。基类实际提供了哪些方法 请参见 组件 API.

-

React.createClass #

ReactClass createClass(object specification)
-
-

给定一份规格(specification),创建一个组件类。组件通常要实现一个 render() 方法,它返回 单个的 子级。该子级可能包含任意深度的子级结构。组件与标准原型类的不同之处在于,你不需要对它们调用 new。 它们是为你在后台构造实例(通过 new)的便利的包装器。

- -

更多关于规格对象(specification object)的信息,请见 组件规格和生命周期

-

React.createElement #

ReactElement createElement(
-  string/ReactClass type,
-  [object props],
-  [children ...]
-)
-
-

创建并返回一个新的给定类型的 ReactElement。type 参数既可以是一个 html 标签名字符串(例如. “div”,“span”,等等),也可以是一个 ReactClass (用 React.createClass 创建的)。

-

React.cloneElement #

ReactElement cloneElement(
-  ReactElement element,
-  [object props],
-  [children ...]
-)
-
-

使用 element 作为起点,克隆并返回一个新的 ReactElement 。生成的 element 将会拥有原始 element 的 props 与新的 props 的浅合并。新的子级将会替换现存的子级。 不同于 React.addons.cloneWithProps,来自原始 element 的 keyref 将会保留。对于合并任何 props 没有特别的行为(不同于 cloneWithProps)。更多细节详见v0.13 RC2 blog post

-

React.createFactory #

factoryFunction createFactory(
-  string/ReactClass type
-)
-
-

返回一个生成给定类型的 ReactElements 的函数。如同 React.createElement,type 参数既可以是一个 html 标签名字符串(例如. “div”,“span”,等等),也可以是一个 ReactClass

-

React.isValidElement #

boolean isValidElement(* object)
-
-

验证对象是否是一个 ReactElement。

-

React.DOM #

-

React.DOMReact.createElement 为 DOM 组件提供了便利的包装器。该方式应该只在不使用 JSX 的时使用。例如,React.DOM.div(null, 'Hello World!')

-

React.PropTypes #

-

React.PropTypes 包含了能与 组件的propTypes 对象一起使用的类型,用以验证传入你的组件的 props。更多有关 propTypes 的信息,请见 可重用组件

-

React.Children #

-

React.Children 为处理 this.props.children 这个不透明的数据结构提供了工具。

-

React.Children.map #

array React.Children.map(object children, function fn [, object thisArg])
-
-

在每一个包含在 children 中的直接子级上调用 fnfn中的 this 设置为 thisArg。如果 children 是一个嵌套的对象或者数组,它将被遍历:不会传入容器对象到 fn 中。如果 children 是 null 或者 undefined,则返回 null 或者 undefined 而不是一个空数组。

-

React.Children.forEach #

React.Children.forEach(object children, function fn [, object thisArg])
-
-

类似 React.Children.map(),但是不返回数组。

-

React.Children.count #

number React.Children.count(object children)
-
-

返回 children 中的组件总数,相等于传递给 map 或者 forEach 的回调函数应被调用次数。

-

React.Children.only #

object React.Children.only(object children)
-
-

返回 children 中仅有的子级。否则抛出异常。

-

React.Children.toArray #

array React.Children.toArray(object children)
-
-

以赋key给每个child的平坦的数组形式,返回不透明的 children 数据结构.如果你想操纵你的渲染方法的子级的合集这很有用,尤其如果你想在 this.props.children 传下之前渲染或者切割.

-

ReactDOM #

-

react-dom 包提供了 具体的DOM方法,这些方法可以在你的app的顶层作为一个你需要时脱离React模式的安全舱口 被使用.你的大多数组件不需要使用这个模块.

-

ReactDOM.render #

ReactComponent render(
-  ReactElement element,
-  DOMElement container,
-  [function callback]
-)
-
-

渲染一个 ReactElement 到 DOM 里提供的 容器(container)中,并返回一个对 组件(或者返回 null 对于 无状态组件) 的引用

- -

如果 ReactElement 之前被渲染到了 container 中,这将对它执行一次更新,并仅变动需要变动的 DOM 来反映最新的 React 组件。

- -

如果提供了可选的回调函数,则该函数将会在组件渲染或者更新之后被执行。

- -
-

注意:

- -

ReactDOM.render() 控制你传入的 container 节点的内容。 - 当初次调用时,任何现存于内的 DOM 元素将被替换。 - 其后的调用使用 React的 diffing 算法来有效率的更新。

- -

ReactDOM.render() 不会修改 container 节点(只修改 container 的子级)。 - 将来,也许能够直接插入一个组件到已经存在的 DOM 节点而不覆盖 - 现有的子级。

-
-

ReactDOM.unmountComponentAtNode #

boolean unmountComponentAtNode(DOMElement container)
-
-

从 DOM 中移除已经挂载的 React 组件,并清除它的事件处理器和 state。如果在 container 中没有组件被挂载,调用此函数将什么都不做。如果组件被卸载返回 true,如果没有组件被卸载返回 false

-

ReactDOM.findDOMNode #

DOMElement findDOMNode(ReactComponent component)
-
-

如果这个组件已经被挂载到了 DOM,它返回相应的浏览器原生的 DOM 元素。这个方法对于读取 DOM 的值很有用,比如表单域的值和执行 DOM 的测量。在大多数情况下,你可以连接一个ref到DOM节点上,并避免使用 findDOMNode 如果 render 返回 null 或者 falsefindDOMNode 返回 null.

- -
-

注意:

- -

findDOMNode() 是一个用来访问底层DOM节点的安全舱口.大多数情况下,使用这个安全舱口是不被鼓励的,因为它穿破了组件的抽象.

- -

findDOMNode() 只在已挂载的组件上工作(即是,已经被放置到DOM里的组件).如果你尝试在没有被挂载的组件上调用这个方法(比如在 一个没有被创建的组件的render()里 调用 findDOMNode() )会抛出一个异常.

- -

findDOMNode() 不能用在无状态组件.

-
-

ReactDOMServer #

-

react-dom/server 允许你在服务器上渲染你的组件.

-

ReactDOMServer.renderToString #

string renderToString(ReactElement element)
-
-

把 ReactElement 渲染为它原始的 HTML 。这应该仅在服务器端使用。React 将会返回一个 HTML 字符串。你可以用这种方法在服务器端生成 HTML,然后在初始请求下传这些标记,以获得更快的页面加载速度及允许搜索引擎抓取页面(便于 SEO)。

- -

如果在一个在已经有了这种服务器预渲染标记的节点上面调用 ReactDOM.render(),React 将会维护该节点,仅绑定事件处理器,让你有一个非常高效的初次加载体验。

-

ReactDOMServer.renderToStaticMarkup #

string renderToStaticMarkup(ReactElement element)
-
-

类似于 renderToString ,除了不创建额外的 DOM 属性,比如 data-react-id,这仅在 React 内部使用的属性。如果你想用 React 做一个简单的静态页面生成器,这是很有用的,因为去除额外的属性能够节省很多字节。

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/top-level-api.html b/docs/top-level-api.html deleted file mode 100644 index 2bdad6ccb8..0000000000 --- a/docs/top-level-api.html +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - - Top-Level API | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Top-Level API -

-
- -

React #

-

React is the entry point to the React library. If you're using one of the prebuilt packages it's available as a global; if you're using CommonJS modules you can require() it.

-

React.Component #

class Component
-
-

This is the base class for React Components when they're defined using ES6 classes. See Reusable Components for how to use ES6 classes with React. For what methods are actually provided by the base class, see the Component API.

-

React.createClass #

ReactClass createClass(object specification)
-
-

Create a component class, given a specification. A component implements a render method which returns one single child. That child may have an arbitrarily deep child structure. One thing that makes components different than standard prototypal classes is that you don't need to call new on them. They are convenience wrappers that construct backing instances (via new) for you.

- -

For more information about the specification object, see Component Specs and Lifecycle.

-

React.createElement #

ReactElement createElement(
-  string/ReactClass type,
-  [object props],
-  [children ...]
-)
-
-

Create and return a new ReactElement of the given type. The type argument can be either an -html tag name string (eg. 'div', 'span', etc), or a ReactClass (created via React.createClass).

-

React.cloneElement #

ReactElement cloneElement(
-  ReactElement element,
-  [object props],
-  [children ...]
-)
-
-

Clone and return a new ReactElement using element as the starting point. The resulting element will have the original element's props with the new props merged in shallowly. New children will replace existing children. Unlike React.addons.cloneWithProps, key and ref from the original element will be preserved. There is no special behavior for merging any props (unlike cloneWithProps). See the v0.13 RC2 blog post for additional details.

-

React.createFactory #

factoryFunction createFactory(
-  string/ReactClass type
-)
-
-

Return a function that produces ReactElements of a given type. Like React.createElement, the type argument can be either an html tag name string (eg. 'div', 'span', etc), or a ReactClass.

-

React.isValidElement #

boolean isValidElement(* object)
-
-

Verifies the object is a ReactElement.

-

React.DOM #

-

React.DOM provides convenience wrappers around React.createElement for DOM components. These should only be used when not using JSX. For example, React.DOM.div(null, 'Hello World!')

-

React.PropTypes #

-

React.PropTypes includes types that can be used with a component's propTypes object to validate props being passed to your components. For more information about propTypes, see Reusable Components.

-

React.Children #

-

React.Children provides utilities for dealing with the this.props.children opaque data structure.

-

React.Children.map #

array React.Children.map(object children, function fn [, object thisArg])
-
-

Invoke fn on every immediate child contained within children with this set to thisArg. If children is a keyed fragment or array it will be traversed: fn will never be passed the container objects. If children is null or undefined returns null or undefined rather than an array.

-

React.Children.forEach #

React.Children.forEach(object children, function fn [, object thisArg])
-
-

Like React.Children.map() but does not return an array.

-

React.Children.count #

number React.Children.count(object children)
-
-

Return the total number of components in children, equal to the number of times that a callback passed to map or forEach would be invoked.

-

React.Children.only #

object React.Children.only(object children)
-
-

Return the only child in children. Throws otherwise.

-

React.Children.toArray #

array React.Children.toArray(object children)
-
-

Return the children opaque data structure as a flat array with keys assigned to each child. Useful if you want to manipulate collections of children in your render methods, especially if you want to reorder or slice this.props.children before passing it down.

- -
-

Note:

- -

React.Children.toArray() changes keys to preserve the semantics of nested arrays when flattening lists of children. That is, toArray prefixes each key in the returned array so that each element's key is scoped to the input array containing it.

-
-

ReactDOM #

-

The react-dom package provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.

-

ReactDOM.render #

render(
-  ReactElement element,
-  DOMElement container,
-  [function callback]
-)
-
-

Render a ReactElement into the DOM in the supplied container and return a reference to the component (or returns null for stateless components).

- -

If the ReactElement was previously rendered into container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React component.

- -

If the optional callback is provided, it will be executed after the component is rendered or updated.

- -
-

Note:

- -

ReactDOM.render() controls the contents of the container node you pass in. Any existing DOM elements -inside are replaced when first called. Later calls use React’s DOM diffing algorithm for efficient -updates.

- -

ReactDOM.render() does not modify the container node (only modifies the children of the container). In -the future, it may be possible to insert a component to an existing DOM node without overwriting -the existing children.

- -

ReactDOM.render() currently returns a reference to the root ReactComponent instance. However, using this return value is legacy -and should be avoided because future versions of React may render components asynchronously in some cases. If you need a reference to the root ReactComponent instance, the preferred solution is to attach a -callback ref to the root element.

-
-

ReactDOM.unmountComponentAtNode #

boolean unmountComponentAtNode(DOMElement container)
-
-

Remove a mounted React component from the DOM and clean up its event handlers and state. If no component was mounted in the container, calling this function does nothing. Returns true if a component was unmounted and false if there was no component to unmount.

-

ReactDOM.findDOMNode #

DOMElement findDOMNode(ReactComponent component)
-
-

If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements. In most cases, you can attach a ref to the DOM node and avoid using findDOMNode at all. When render returns null or false, findDOMNode returns null.

- -
-

Note:

- -

findDOMNode() is an escape hatch used to access the underlying DOM node. In most cases, use of this escape hatch is discouraged because it pierces the component abstraction.

- -

findDOMNode() only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like calling findDOMNode() in render() on a component that has yet to be created) an exception will be thrown.

- -

findDOMNode() cannot be used on stateless components.

-
-

ReactDOMServer #

-

The react-dom/server package allows you to render your components on the server.

-

ReactDOMServer.renderToString #

string renderToString(ReactElement element)
-
-

Render a ReactElement to its initial HTML. This should only be used on the server. React will return an HTML string. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.

- -

If you call ReactDOM.render() on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.

-

ReactDOMServer.renderToStaticMarkup #

string renderToStaticMarkup(ReactElement element)
-
-

Similar to renderToString, except this doesn't create extra DOM attributes such as data-react-id, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/transferring-props-it-IT.html b/docs/transferring-props-it-IT.html deleted file mode 100644 index 786301fe9c..0000000000 --- a/docs/transferring-props-it-IT.html +++ /dev/null @@ -1,614 +0,0 @@ - - - - - - - Trasferimento delle Proprietà | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Trasferimento delle Proprietà -

-
- -

Un pattern comune in React è l'uso di un'astrazione per esporre un componente. Il componente esterno espone una semplice proprietà per effettuare un'azione che può richiedere un'implementazione più complessa.

- -

Puoi usare gli attributi spread di JSX per unire le vecchie props con valori aggiuntivi:

-
<Component {...this.props} more="values" />
-
-

Se non usi JSX, puoi usare qualsiasi helper come l'API Object.assign di ES6, o il metodo _.extend di Underscore:

-
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
-
-

Nel resto di questo tutorial vengono illustrate le best practices, usando JSX e sintassi sperimentale di ES7.

-

Trasferimento Manuale #

-

Nella maggior parte dei casi dovresti esplicitamente passare le proprietà. Ciò assicura che venga esposto soltanto un sottoinsieme dell'API interna, del cui funzionamento si è certi.

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    <div className={fancyClass} onClick={props.onClick}>
-      {props.children}
-    </div>
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Ciao mondo!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-

E se aggiungessimo una proprietà name? O una proprietà title? O onMouseOver?

-

Trasferire con ... in JSX #

-
-

NOTA:

- -

La sintassi ... fa parte della proposta Object Rest Spread. Questa proposta è in processo di diventare uno standard. Consulta la sezione Proprietà Rest e Spread ... di seguito per maggiori dettagli.

-
- -

A volte passare manualmente ciascuna proprietà può essere noioso e fragile. In quei casi puoi usare l'assegnamento destrutturante con le proprietà residue per estrarre un insieme di proprietà sconosciute.

- -

Elenca tutte le proprietà che desideri consumare, seguite da ...other.

-
var { checked, ...other } = props;
-
-

Ciò assicura che vengano passate tutte le proprietà TRANNE quelle che stai consumando tu stesso.

-
function FancyCheckbox(props) {
-  var { checked, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  // `other` contiene { onClick: console.log } ma non la proprietà checked
-  return (
-    <div {...other} className={fancyClass} />
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Ciao mondo!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-
-

NOTA:

- -

Nell'esempio precedente, la proprietà checked è anche un attributo DOM valido. Se non utilizzassi la destrutturazione in questo modo, potresti inavvertitamente assegnarlo al div.

-
- -

Usa sempre il pattern di destrutturazione quando trasferisci altre proprietà sconosciute in other.

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  // ANTI-PATTERN: `checked` sarebbe passato al componente interno
-  return (
-    <div {...props} className={fancyClass} />
-  );
-}
-

Consumare e Trasferire la Stessa Proprietà #

-

Se il tuo componente desidera consumare una proprietà, ma anche passarla ad altri, puoi passarla esplicitamente mediante checked={checked}. Questo è preferibile a passare l'intero oggetto this.props dal momento che è più facile effettuarne il linting e il refactoring.

-
function FancyCheckbox(props) {
-  var { checked, title, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  var fancyTitle = checked ? 'X ' + title : 'O ' + title;
-  return (
-    <label>
-      <input {...other}
-        checked={checked}
-        className={fancyClass}
-        type="checkbox"
-      />
-      {fancyTitle}
-    </label>
-  );
-}
-
-
-

NOTA:

- -

L'ordine è importante. Mettendo il {...other} prima delle tue proprietà JSX ti assicuri che il consumatore del tuo componente non possa ridefinirle. Nell'esempio precedente, abbiamo garantito che l'elemento input sarà del tipo "checkbox".

-
-

Proprietà Rest e Spread ... #

-

Le proprietà Rest ti permettono di estrarre le proprietà residue di un oggetto in un nuovo oggetto. Vengono escluse tutte le altre proprietà elencate nel pattern di destrutturazione.

- -

Questa è un'implementazione sperimentale di una proposta ES7.

-
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
-x; // 1
-y; // 2
-z; // { a: 3, b: 4 }
-
-
-

Nota:

- -

Questa proposta ha raggiunto lo stadio 2 ed è attivata in modo predefinito in Babel. Vecchie versioni di Babel potrebbero richiedere l'abilitazione esplicita di questa trasformazione con babel --optional es7.objectRestSpread

-
-

Trasferire con Underscore #

-

Se non usi JSX, puoi usare una libreria per ottenere il medesimo pattern. Underscore supporta _.omit per omettere delle proprietà ed _.extend per copiare le proprietà in un nuovo oggetto.

-
function FancyCheckbox(props) {
-  var checked = props.checked;
-  var other = _.omit(props, 'checked');
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    React.DOM.div(_.extend({}, other, { className: fancyClass }))
-  );
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/transferring-props-ja-JP.html b/docs/transferring-props-ja-JP.html deleted file mode 100644 index 726bb8067a..0000000000 --- a/docs/transferring-props-ja-JP.html +++ /dev/null @@ -1,610 +0,0 @@ - - - - - - - propsの移譲 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- propsの移譲 -

-
- -

コンポーネントを抽象的にラップすることはReactにおいて共通のパターンです。外のコンポーネントは単純なプロパティを表示し、中ではさらに複雑なインプリメンテーションの詳細を持つようになっています。

- -

以下のように、古いpropsと追加の値をJSXの拡張属性を使ってマージすることができます。

-
<Component {...this.props} more="values" />
-
-

JSXを使わない場合は、以下のように、ES6の Object.assign か Underscore の _.extend といったオブジェクトヘルパーを使うことができます。

-
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
-
-

以下のチュートリアルはベストプラクティスを提示しています。JSXや試験的なES7のシンタックスを使っています。

-

手動での移動 #

-

ほとんどの場合、プロパティを明確に子要素に渡すべきです。それは、内部のAPIのサブセットだけを外に出していることと、認識しているプロパティが動作することを保証します。

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    <div className={fancyClass} onClick={props.onClick}>
-      {props.children}
-    </div>
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Hello world!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-

しかし、 name プロパティや title プロパティや onMouseOver はどうでしょうか?

-

JSXにおける ... を使った移譲 #

-
-

注意: -以下の例では、実験的なES7のシンタックスであることを示すために --harmony フラグが必要になります。ブラウザ上でJSXトランスフォーマーを使う際には、単純に <script type="text/jsx;harmony=true"> を使ってスクリプトを読み込んでください。詳細については、 レストとスプレッドのプロパティ ...をご覧ください。

-
- -

全てのプロパティを渡すのはバグを生みやすく、面倒くさいときがあります。そのようなケースでは、未知のプロパティのセットを使うためにレストプロパティと共に分割代入引数を使うことができます。

- -

以下のように ...other を使うことで、使いたいプロパティを一覧にすることができます。

-
var { checked, ...other } = props;
-
-

これは、自分で指定したものは 除き 、全てのpropsを渡すことを保証します。

-
function FancyCheckbox(props) {
-  var { checked, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  // `other` は { onClick: console.log } を含みますが、 checked プロパティは含みません。
-  return (
-    <div {...other} className={fancyClass} />
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Hello world!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-
-

注意: -上の例では、 checked propは正式なDOMの属性でもあります。この方法を使って分割代入を行わない場合は、無意識的に渡すこともできます。

-
- -

未知の other propsを移譲する際には、分割代入パターンを常に使ってください。

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  // アンチパターン: `checked` が内部のコンポーネントに渡されます。
-  return (
-    <div {...props} className={fancyClass} />
-  );
-}
-

同じpropを使い、移譲する #

-

コンポーネントがプロパティを使うだけでなく、子要素に渡したい場合は、明確に checked={checked} と記述することで再度渡すことができます。 this.props オブジェクトで全てを渡すほうが、リファクタリングやチェックをしやすいので好ましいです。

-
function FancyCheckbox(props) {
-  var { checked, title, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  var fancyTitle = checked ? 'X ' + title : 'O ' + title;
-  return (
-    <label>
-      <input {...other}
-        checked={checked}
-        className={fancyClass}
-        type="checkbox"
-      />
-      {fancyTitle}
-    </label>
-  );
-}
-
-
-

注意: -順番の問題です。JSXのpropsの前に {...other} を置くことで、コンポーネントの使用者がオーバーライドできないことを保証します。上の例ではinputが "checkbox" 型であることを保証しました。

-
-

レストとスプレッドのプロパティ ... #

-

レストプロパティはあるオブジェクトの残りの要素を新しいオブジェクトに引き抜きます。分割代入パターンでリストになっている全てのプロパティを外に出します。

- -

これは、ES7プロポーサルの実験的な実行です。

-
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
-x; // 1
-y; // 2
-z; // { a: 3, b: 4 }
-
-
-

注意: -実験的なES7のシンタックスを有効にするには、 --harmony フラグをJSXコマンドラインツールで使用してください。

-
-

Underscoreによる移譲 #

-

JSXを使わない際には、同じパターンを行うライブラリを使うことができます。Underscoreでは、 _.omit を使ってプロパティをフィルタしたり、 _.extend を使って新しいオブジェクトにプロパティをコピーしたりできます。

-
function FancyCheckbox(props) {
-  var checked = props.checked;
-  var other = _.omit(props, 'checked');
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    React.DOM.div(_.extend({}, other, { className: fancyClass }))
-  );
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/transferring-props-ko-KR.html b/docs/transferring-props-ko-KR.html deleted file mode 100644 index 3c0fed2dc9..0000000000 --- a/docs/transferring-props-ko-KR.html +++ /dev/null @@ -1,616 +0,0 @@ - - - - - - - Props 전달 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Props 전달 -

-
- -

React에서는 컴포넌트를 감싸서 추상화하는 것이 일반적인 패턴입니다. 외부 컴포넌트에서는 간단한 프로퍼티만을 노출하여 복잡한 세부 구현을 감출 수 있습니다.

- -

JSX 스프레드 어트리뷰트를 통해 props에 추가적인 값을 병합할 수 있습니다.

-
<Component {...this.props} more="values" />
-
-

만약 JSX를 사용하지 않는다면 ES6의 Object.assign나 Underscore의 _.extend 같은 객체 헬퍼를 사용할 수 있습니다:

-
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
-
-

이 튜토리얼의 나머지 부분은 모범 답안을 소개할 것입니다. JSX와 실험적인 ES7 구문을 사용합니다.

-

수동적인 전달 #

-

대부분의 경우 명시적으로 프로퍼티를 아래로 전달해야 합니다. 이는 동작을 확신하는 내부 API의 일부만 공개하도록 합니다.

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    <div className={fancyClass} onClick={props.onClick}>
-      {props.children}
-    </div>
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    세상아 안녕!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-

하지만 name이나 title, onMouseOver 같은 prop들이 더 추가된다면 어떨까요?

-

JSX에서 ...를 사용해 전달하기 #

-
-

주의:

- -

... 구문은 객체 잔여 스프레드 제안의 일부입니다. 이 제안은 표준화 과정에 있습니다. 더 자세한 내용은 밑의 잔여 프로퍼티와 스프레드 프로퍼티 ... 부분을 참고하세요.

-
- -

때로는 모든 프로퍼티를 일일이 전달 하는것은 지루하고 덧없는 작업입니다. 이 경우 구조 해체 할당(destructuring assignment)을 다른 프로퍼티를 함께 사용해 미상의 프로퍼티를 추출할 수 있습니다.

- -

소비할 프로퍼티들을 나열하고, 그 뒤에 ...other를 넣습니다.

-
var { checked, ...other } = props;
-
-

이는 지금 소비한 props를 제외한 나머지를 아래로 전달합니다.

-
function FancyCheckbox(props) {
-  var { checked, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  // `other`에는 { onClick: console.log }가 포함되지만 checked 프로퍼티는 제외됩니다
-  return (
-    <div {...other} className={fancyClass} />
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    세상아 안녕!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-
-

주의:

- -

위의 예제에서는 checked prop 또한 마찬가지로 유효한 DOM 어트리뷰트입니다. 이런 식으로 구조의 해체(destructuring)를 하지 않으면 의도하지 않게 함께 전달될 수 있습니다.

-
- -

미상의 other props을 전달할 때는 항상 구조 해체 패턴을 사용하세요.

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  // 반례: `checked` 또한 내부 컴포넌트로 전달될 것입니다
-  return (
-    <div {...props} className={fancyClass} />
-  );
-}
-

같은 Prop을 소비하고 전달하기 #

-

컴포넌트가 프로퍼티를 사용하지만 계속 넘기길 원한다면, checked={checked}처럼 명시적으로 다시 넘길 수 있습니다. 리팩토링과 린트(lint)하기가 더 쉬우므로 이 방식이 this.props 객체 전부를 넘기는 것보다 낫습니다.

-
function FancyCheckbox(props) {
-  var { checked, title, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  var fancyTitle = checked ? 'X ' + title : 'O ' + title;
-  return (
-    <label>
-      <input {...other}
-        checked={checked}
-        className={fancyClass}
-        type="checkbox"
-      />
-      {fancyTitle}
-    </label>
-  );
-}
-
-
-

주의:

- -

순서는 중요합니다. {...other}를 JSX props 이전에 넣는 것으로 컴포넌트의 사용자가 확실히 그것들을 오버라이드 할 수 없게 합니다. 위의 예제에서는 input이 "checkbox" 타입인 것을 보장합니다.

-
- -

-

잔여 프로퍼티와 스프레드 프로퍼티 ... #

-

잔여(Rest, ...) 프로퍼티는 객체에서 소비되지 않은 나머지 프로퍼티를 추출해 새로운 객체로 만들 수 있게 해 줍니다. 구조 해체 패턴에서 열거된 다른 프로퍼티들은 모두 제외됩니다.

- -

이 제안은 2 단계에 돌입해 이제 바벨에서 기본값으로 활성화되어있습니다. 바벨의 이전 버전은 babel --optional es7.objectRestSpread로 명시적으로 활성화 할 필요가 있을 수도 있습니다.

-
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
-x; // 1
-y; // 2
-z; // { a: 3, b: 4 }
-
-
-

주의:

- -

실험적인 ES7 구문을 활성화하려면 JSX 커맨드라인 도구--harmony 플래그와 함께 사용하세요.

-
-

Underscore로 전달 다루기 #

-

JSX를 사용하지 않는다면 라이브러리를 사용해 같은 패턴을 쓸 수 있습니다. Underscore에서는 _.omit을 사용해 특정 프로퍼티를 제외하거나 _.extend를 사용해 새로운 객체로 프로퍼티를 복사할 수 있습니다.

-
function FancyCheckbox(props) {
-  var checked = props.checked;
-  var other = _.omit(props, 'checked');
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    React.DOM.div(_.extend({}, other, { className: fancyClass }))
-  );
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/transferring-props-zh-CN.html b/docs/transferring-props-zh-CN.html deleted file mode 100644 index 32da9b0cd5..0000000000 --- a/docs/transferring-props-zh-CN.html +++ /dev/null @@ -1,614 +0,0 @@ - - - - - - - 传递 Props | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 传递 Props -

-
- -

React 里有一个非常常用的模式就是对组件做一层抽象。组件对外公开一个简单的属性(Props)来实现功能,但内部的实现可能非常复杂。

- -

可以使用 JSX 展开属性 来合并现有的 props 和其它值:

-
<Component {...this.props} more="values" />
-
-

如果不使用 JSX,可以使用一些对象辅助方法如 ES6 的 Object.assign 或 Underscore _.extend

-
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
-
-

下面的教程介绍一些最佳实践。使用了 JSX 和 试验性的ECMAScript 语法。

-

手动传递 #

-

大部分情况下你应该显式地向下传递 props。这样可以确保只公开你认为是安全的内部 API 的子集。

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    <div className={fancyClass} onClick={props.onClick}>
-      {props.children}
-    </div>
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Hello world!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-

name 这个属性怎么办?还有 titleonMouseOver 这些 props?

-

在 JSX 里使用 ... 传递 #

-
-

注意:

- -

在下面的例子中,--harmony 标志是必须的因为这个语法是ES7的实验性语法。如果用浏览器中的JSX转换器,以 <script type="text/jsx;harmony=true">简单的打开你脚本就行了。详见Rest and Spread Properties ...

-
- -

有时把所有属性都传下去是不安全或啰嗦的。这时可以使用 解构赋值 中的剩余属性特性来把未知属性批量提取出来。

- -

列出所有当前要使用的属性,后面跟着 ...other

-
var { checked, ...other } = props;
-
-

这样能确保把所有 props 传下去,除了 那些已经被使用了的。

-
function FancyCheckbox(props) {
-  var { checked, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  // `other` 包含 { onClick: console.log } 但 checked 属性除外
-  return (
-    <div {...other} className={fancyClass} />
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Hello world!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-
-

注意:

- -

上面例子中,checked 属性也是一个有效的 DOM 属性。如果你没有使用解构赋值,那么可能无意中把它传下去。

-
- -

在传递这些未知的 other 属性时,要经常使用解构赋值模式。

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  // 反模式:`checked` 会被传到里面的组件里
-  return (
-    <div {...props} className={fancyClass} />
-  );
-}
-

使用和传递同一个 Prop #

-

如果组件需要使用一个属性又要往下传递,可以直接使用 checked={checked} 再传一次。这样做比传整个 props 对象要好,因为更利于重构和语法检查。

-
function FancyCheckbox(props) {
-  var { checked, title, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  var fancyTitle = checked ? 'X ' + title : 'O ' + title;
-  return (
-    <label>
-      <input {...other}
-        checked={checked}
-        className={fancyClass}
-        type="checkbox"
-      />
-      {fancyTitle}
-    </label>
-  );
-}
-
-
-

注意:

- -

顺序很重要,把 {...other} 放到 JSX props 前面会使 props 不会被覆盖。上面例子中我们可以保证 input 的 type 是 "checkbox"

-
-

剩余属性和展开属性 ... #

-

剩余属性可以把对象剩下的属性提取到一个新的对象。这会把所有在解构赋值中列出的属性剔除。

- -

这是 ECMAScript 草案 中的试验特性。

-
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
-x; // 1
-y; // 2
-z; // { a: 3, b: 4 }
-
-
-

注意:

- -

要用 Babel 6转换 rest 和 spread 属性,你需要安装 es2015 preset,transform-object-rest-spread 插件并在 .babelrc 里配置他们.

-
-

使用 Underscore 来传递 #

-

如果不使用 JSX,可以使用一些库来实现相同效果。Underscore 提供 _.omit 来过滤属性,_.extend 复制属性到新的对象。

-
function FancyCheckbox(props) {
-  var checked = props.checked;
-  var other = _.omit(props, 'checked');
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    React.DOM.div(_.extend({}, other, { className: fancyClass }))
-  );
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/transferring-props.html b/docs/transferring-props.html deleted file mode 100644 index 8496f562e9..0000000000 --- a/docs/transferring-props.html +++ /dev/null @@ -1,614 +0,0 @@ - - - - - - - Transferring Props | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Transferring Props -

-
- -

It's a common pattern in React to wrap a component in an abstraction. The outer component exposes a simple property to do something that might have more complex implementation details.

- -

You can use JSX spread attributes to merge the old props with additional values:

-
<Component {...this.props} more="values" />
-
-

If you don't use JSX, you can use any object helper such as ES6 Object.assign or Underscore _.extend:

-
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
-
-

The rest of this tutorial explains best practices. It uses JSX and experimental ECMAScript syntax.

-

Manual Transfer #

-

Most of the time you should explicitly pass the properties down. This ensures that you only expose a subset of the inner API, one that you know will work.

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    <div className={fancyClass} onClick={props.onClick}>
-      {props.children}
-    </div>
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Hello world!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-

But what about the name prop? Or the title prop? Or onMouseOver?

-

Transferring with ... in JSX #

-
-

NOTE:

- -

The ... syntax is part of the Object Rest Spread proposal. This proposal is on track to become a standard. See the Rest and Spread Properties ... section below for more details.

-
- -

Sometimes it's fragile and tedious to pass every property along. In that case you can use destructuring assignment with rest properties to extract a set of unknown properties.

- -

List out all the properties that you would like to consume, followed by ...other.

-
var { checked, ...other } = props;
-
-

This ensures that you pass down all the props EXCEPT the ones you're consuming yourself.

-
function FancyCheckbox(props) {
-  var { checked, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  // `other` contains { onClick: console.log } but not the checked property
-  return (
-    <div {...other} className={fancyClass} />
-  );
-}
-ReactDOM.render(
-  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
-    Hello world!
-  </FancyCheckbox>,
-  document.getElementById('example')
-);
-
-
-

NOTE:

- -

In the example above, the checked prop is also a valid DOM attribute. If you didn't use destructuring in this way you might inadvertently pass it along.

-
- -

Always use the destructuring pattern when transferring unknown other props.

-
function FancyCheckbox(props) {
-  var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
-  // ANTI-PATTERN: `checked` would be passed down to the inner component
-  return (
-    <div {...props} className={fancyClass} />
-  );
-}
-

Consuming and Transferring the Same Prop #

-

If your component wants to consume a property but also wants to pass it along, you can repass it explicitly with checked={checked}. This is preferable to passing the full props object since it's easier to refactor and lint.

-
function FancyCheckbox(props) {
-  var { checked, title, ...other } = props;
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  var fancyTitle = checked ? 'X ' + title : 'O ' + title;
-  return (
-    <label>
-      <input {...other}
-        checked={checked}
-        className={fancyClass}
-        type="checkbox"
-      />
-      {fancyTitle}
-    </label>
-  );
-}
-
-
-

NOTE:

- -

Order matters. By putting the {...other} before your JSX props you ensure that the consumer of your component can't override them. In the example above we have guaranteed that the input will be of type "checkbox".

-
-

Rest and Spread Properties ... #

-

Rest properties allow you to extract the remaining properties from an object into a new object. It excludes every other property listed in the destructuring pattern.

- -

This is an experimental implementation of an ECMAScript proposal.

-
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
-x; // 1
-y; // 2
-z; // { a: 3, b: 4 }
-
-
-

Note:

- -

To transform rest and spread properties using Babel 6, you need to install the es2015 preset, the transform-object-rest-spread plugin and configure them in the .babelrc file.

-
-

Transferring with Underscore #

-

If you don't use JSX, you can use a library to achieve the same pattern. Underscore supports _.omit to filter out properties and _.extend to copy properties onto a new object.

-
function FancyCheckbox(props) {
-  var checked = props.checked;
-  var other = _.omit(props, 'checked');
-  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
-  return (
-    React.DOM.div(_.extend({}, other, { className: fancyClass }))
-  );
-}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tutorial-it-IT.html b/docs/tutorial-it-IT.html deleted file mode 100644 index 1da620e366..0000000000 --- a/docs/tutorial-it-IT.html +++ /dev/null @@ -1,1100 +0,0 @@ - - - - - - - Tutorial | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Tutorial -

-
- -

Costruiremo una semplice ma realistica casella dei commenti che puoi inserire in un blog, una versione base dei commenti in tempo reale offerti da Disqus, LiveFyre o Facebook.

- -

Forniremo:

- -
    -
  • Una vista di tutti i commenti
  • -
  • Un modulo per inviare un commento
  • -
  • Hook perché tu fornisca un backend personalizzato
  • -
- -

Avrà anche un paio di caratteristiche interessanti:

- -
    -
  • Commenti ottimistici: i commenti appaiono nella lista prima che vengano salvati sul server, in modo da sembrare più veloce.
  • -
  • Aggiornamenti in tempo reale: i commenti degli altri utenti sono aggiunti alla vista dei commenti in tempo reale.
  • -
  • Formattazione Markdown: gli utenti possono utilizzare il Markdown per formattare il proprio testo.
  • -
-

Vuoi saltare tutto questo e vedere semplicemente il sorgente? #

-

It's all on GitHub.

-

Eseguire un server #

-

Per cominciare questo tutorial dobbiamo richiedere un server in esecuzione. Questo servirà puramente come un endpoint per le API che useremo per ottenere e salvare i dati. Per rendere questo compito il più semplice possibile, abbiamo creato un seplice server in un numero di linguaggi di scripting che fa esattamente ciò che ci serve. Puoi leggere il sorgente o scaricare un file zip contenente tutto ciò che ti serve per cominciare.

- -

Per semplicità, il server che eseguiremo usa un file JSON come database. Non è ciò che eseguiresti in produzione, ma rende più facile simulare ciò che faresti per consumare una API. Non appena avvii il server, supporterà il nostro endpoint API e servirà anche le pagine statiche di cui abbiamo bisogno.

-

Per Cominciare #

-

Per questo tutorial renderemo il tutto il più semplice possibile. Incluso nel pacchetto del server discusso in precedenza si trova un file HTML su cui lavoreremo. Apri public/index.html nel tuo editor preferito. Dovrebbe apparire simile a quanto segue (con qualche piccola differenza, aggiungeremo un tag <script> aggiuntivo in seguito):

-
<!-- index.html -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8" />
-    <title>React Tutorial</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-    <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-    <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-  </head>
-  <body>
-    <div id="content"></div>
-    <script type="text/babel" src="scripts/example.js"></script>
-    <script type="text/babel">
-      // To get started with this tutorial running your own code, simply remove
-      // the script tag loading scripts/example.js and start writing code here.
-    </script>
-  </body>
-</html>
-
-

Nel resto di questo tutorial, scriveremo il nostro codice JavaScript in questo tag script. Non disponiamo di alcun aggiornamento in tempo reale avanzato, quindi dovremo aggiornare il browser per vedere gli aggiornamenti dopo il salvataggio. Segui il tuo progresso aprendo http://localhost:3000 nel tuo browser (dopo aver avviato il server). Quando carichi la pagina per la prima volta senza apportare cambiamenti, vedrai il risultato finale di ciò che ci apprestiamo a costruire. Quando sei pronto per cominciare a lavorare, elimina il tag <script> precedente e quindi sei pronto a continuare.

- -
-

Nota:

- -

Abbiamo incluso jQuery perché vogliamo semplificare il codice delle nostre chiamate ajax future, ma NON è richiesto per far funzionare React.

-
-

Il tuo primo componente #

-

In React ciò che importa sono i componenti modulari e componibili. Per il nostro esempio della casella dei commenti, avremo la seguente struttura dei componenti:

-
- CommentBox
-  - CommentList
-    - Comment
-  - CommentForm
-
-

Costruiamo il componente CommentBox, che consiste in un semplice <div>:

-
// tutorial1.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        Ciao, mondo! Sono un CommentBox.
-      </div>
-    );
-  }
-});
-ReactDOM.render(
-  <CommentBox />,
-  document.getElementById('content')
-);
-
-

Nota che i nomi degli elementi nativi HTML cominciano con una lettera minuscola, mentre i nomi di classe personalizzati di React cominciano con una lettera maiuscola.

-

Sintassi JSX #

-

La prima cosa che noterai è la sintassi simile a XML nel tuo JavaScript. Abbiamo un semplice preprocessore che traduce lo zucchero sintattico a questo semplice JavaScript:

-
// tutorial1-raw.js
-var CommentBox = React.createClass({displayName: 'CommentBox',
-  render: function() {
-    return (
-      React.createElement('div', {className: "commentBox"},
-        "Ciao, mondo! Sono un CommentBox."
-      )
-    );
-  }
-});
-ReactDOM.render(
-  React.createElement(CommentBox, null),
-  document.getElementById('content')
-);
-
-

Il suo uso è opzionale ma abbiamo trovato la sintassi JSX più facile da usare del semplice JavaScript. Leggi maggiori dettagli sull'articolo sulla sintassi JSX.

-

Cosa sta succedendo? #

-

Passiamo dei metodi in un oggetto JavaScript a React.createClass() per creare un nuovo componente React. Il più importante di questi metodi è chiamato render il quale restituisce un albero di componenti React che saranno eventualmente visualizzati come HTML.

- -

I tag <div> non sono veri nodi DOM; sono istanze dei componenti React div. Puoi pensare a questi come marcatori o a elementi di dati che React sa come gestire. React è sicuro. Non stiamo generando stringhe HTML quindi la protezione XSS è predefinita.

- -

Non devi necessariamente restituire semplice HTML. Puoi anche restituire un albero di componenti costruiti da te (o da qualcun altro). Questo è ciò che rende React componibile: una caratteristica chiave dei front-end manutenibili.

- -

ReactDOM.render() istanzia il componente radice, avvia il framework, e inietta il markup in un elemento DOM nativo, fornito come secondo argomento.

-

Comporre componenti #

-

Costruiamo degli scheletri per CommentList e CommentForm che saranno, nuovamente, dei semplici <div>. Aggiungi questi due componenti al tuo file, mantenendo la dichiarazione esistente di CommentBox e la chiamata a ReactDOM.render:

-
// tutorial2.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        Hello, world! I am a CommentList.
-      </div>
-    );
-  }
-});
-
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <div className="commentForm">
-        Hello, world! I am a CommentForm.
-      </div>
-    );
-  }
-});
-
-

Successivamente, aggiorna il componente CommentBox per utilizzare questi due nuovi componenti:

-
// tutorial3.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

Nota come stiamo mescolando tag HTML e i componenti che abbiamo costruito. I componenti HTML sono componenti regolari React, proprio come quelli che definisci, con una differenza. Il compilatore JSX riscriverà automaticamente i tag HTML come espressioni React.createElement(tagName) e lascerà tutto il resto inalterato. Questo è per impedire che il namespace globale venga inquinato.

-

Usare le proprietà #

-

Creiamo il componente Comment, che dipenderà dai dati passatigli dal suo genitore. I dati passati da un componente genitore sono disponibili come una 'proprietà' nel componente figlio. Queste 'proprietà' sono accessibili attraverso this.props. Usando le proprietà, saremo in grado di leggere i dati passati al componente Comment dal componente CommentList, e visualizzare del markup:

-
// tutorial4.js
-var Comment = React.createClass({
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {this.props.children}
-      </div>
-    );
-  }
-});
-
-

Racchiudendo un'espressione JavaScript dentro parentesi graffe all'interno di JSX (sia come attributo che come figlio), puoi inserire del testo o componenti React all'interno dell'albero. Accediamo per nome ad attributi passati al componente tramite chiavi in this.props e ciascun elemento annidato come this.props.children.

-

Proprietà dei Componenti #

-

Adesso che abbiamo definito il componente Comment, vogliamo passargli il nome dell'autore e il testo del commento. Questo ci permette di riutilizzare lo stesso codice per ciascun commento individuale. Ora aggiungiamo dei commenti all'interno del nostro CommentList:

-
// tutorial5.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        <Comment author="Pete Hunt">Questo è un commento</Comment>
-        <Comment author="Jordan Walke">Questo è un *altro* commento</Comment>
-      </div>
-    );
-  }
-});
-
-

Nota che abbiamo passato dei dati dal componente genitore CommentList al componente figlio Comment. Ad esempio, abbiamo passato Pete Hunt (tramite un attributo) e Questo è un commento (tramite un nodo figlio simil-XML) al primo Comment. Come detto in precedenza, il componente Comment accederà a queste 'proprietà' attraverso this.props.author e this.props.children.

-

Aggiungiamo il Markdown #

-

Il Markdown è una maniera semplice di formattare il tuo testo in linea. Ad esempio, racchiudendo il testo con asterischi gli aggiungerà dell'enfasi.

- -

Per prima cosa, aggiungiamo la libreria di terze parti marked alla tua applicazione. Questa è una libreria JavaScript che prende il testo Markdown e lo converte in HTML nativo. Per fare ciò è richiesto un tag script nel tag head (che abbiamo già incluso nel playground React):

-
<!-- index.html -->
-<head>
-  <meta charset="utf-8" />
-  <title>React Tutorial</title>
-  <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-  <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-  <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-  <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-</head>
-
-

Successivamente, convertiamo il testo del commento da Markdown e scriviamolo:

-
// tutorial6.js
-var Comment = React.createClass({
-  render: function() {
-    var md = new Remarkable();
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {md.render(this.props.children.toString())}
-      </div>
-    );
-  }
-});
-
-

Tutto ciò che stiamo facendo qui è chiamare la libreria remarkable. Dobbiamo convertire this.props.children dal testo racchiuso di React a una stringa che remarkable è in grado di capire, quindi vi chiamiamo esplicitamente toString().

- -

Ma c'è un problema! I nostri commenti visualizzati appaiono come segue nel browser: "<p>Questo è un <em>altro</em> commento</p>". Noi vogliamo che questi tag vengano in realtà visualizzati come HTML.

- -

Questo è il risultato della protezione di React da parte di un attacco XSS. C'è una maniera di aggirare questo comportamento, ma il framework ti avvisa di non farlo:

-
// tutorial7.js
-var Comment = React.createClass({
-  rawMarkup: function() {
-    var md = new Remarkable();
-    var rawMarkup = md.render(this.props.children.toString());
-    return { __html: rawMarkup };
-  },
-
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        <span dangerouslySetInnerHTML={this.rawMarkup()} />
-      </div>
-    );
-  }
-});
-
-

Questa è una speciale API che rende intenzionalmente difficile inserire HTML nativo, ma per remarkable ci avvantaggeremo di questa possibilità.

- -

Ricorda: usando questa funzionalità stai assumendo che remarkable sia sicuro.

-

Collega il modello dei dati #

-

Finora abbiamo inserito i commenti direttamente nel codice sorgente. Invece, visualizziamo un pacchetto di dati JSON nella lista dei commenti. In seguito questi verranno restituiti dal server, ma per adesso scriviamoli nel tuo sorgente:

-
// tutorial8.js
-var data = [
-  {author: "Pete Hunt", text: "Questo è un commento"},
-  {author: "Jordan Walke", text: "Questo è un *altro* commento"}
-];
-
-

Dobbiamo inserire questi dati in CommentList in maniera modulare. Modifica CommentBox e la chiamata a ReactDOM.render() per passare questi dati a CommentList tramite proprietà:

-
// tutorial9.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList data={this.props.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox data={data} />,
-  document.getElementById('content')
-);
-
-

Adesso che i dati sono disponibili in CommentList, visualizziamo i commenti dinamicamente:

-
// tutorial10.js
-var CommentList = React.createClass({
-  render: function() {
-    var commentNodes = this.props.data.map(function (comment) {
-      return (
-        <Comment author={comment.author} key={comment.id}>
-          {comment.text}
-        </Comment>
-      );
-    });
-    return (
-      <div className="commentList">
-        {commentNodes}
-      </div>
-    );
-  }
-});
-
-

Tutto qui!

-

Richiedere dati dal server #

-

Sostituiamo i dati scritti nel codice con dati dinamici ottenuti dal server. Rimuoveremo le proprietà dei dati e le sostituiremo con uno URL da richiedere:

-
// tutorial11.js
-ReactDOM.render(
-  <CommentBox url="/api/comments" />,
-  document.getElementById('content')
-);
-
-

Questo componente differisce dal precedente perché dovrà effettuare un nuovo rendering di se stesso. Il componente non avrà dati finché la risposta del server non sia disponibile, e a quel punto il componente potrebbe dover visualizzare dei nuovi commenti.

- -

Nota: il codice non funzionerà a questo passo.

-

Stato reattivo #

-

Finora, basandosi sulle sue proprietà, ogni componente si è visualizzato solo una volta. I valori di props sono immutabili: sono passati dal genitore e sono "posseduti" dal genitore. Per implementare le interazioni, introduciamo uno stato mutevole nel componente. this.state è privato al componente e può essere cambiato chiamando this.setState(). Quando lo stato si aggiorna, il componente effettua nuovamente il rendering di se stesso.

- -

I metodi render() sono scritti dichiarativamente come funzioni di this.props e this.state. Il framework garantisce che la UI sia sempre consistente con gli input.

- -

Quando il server ci fornisce i dati, dovremo cambiare i dati dei commenti in nostro possesso. Aggiungiamo un array di dati dei commenti al componente CommentBox come il suo stato:

-
// tutorial12.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

getInitialState() viene eseguito esattamente una volta durante il ciclo di vita del componente e imposta lo stato iniziale del componente stesso.

-

Aggiornare lo stato #

-

Quando il componente è creato per la prima volta, vogliamo richiedere tramite GET del JSON dal server e aggiornare lo stato per riflettere i dati più recenti. Useremo jQuery per effettuare una richiesta asincrona al server che abbiamo avviato in precedenza per richiedere i dati che ci servono. Somiglieranno a qualcosa di simile:

-
[
-  {"author": "Pete Hunt", "text": "Questo è un commento"},
-  {"author": "Jordan Walke", "text": "Questo è un *altro* commento"}
-]
-
// tutorial13.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

Qui, componentDidMount è un metodo chiamato automaticamente da React quando un componente viene visualizzato. La chiave agli aggiornamenti dinamici è la chiamata a this.setState(). Sostituiamo il vecchio array di commenti con il nuovo ottenuto dal server e la UI si aggiorna automaticamente. Per via di questa reattività, è richiesto soltanto un piccolo cambiamento per aggiungere gli aggiornamenti in tempo reale. Qui useremo un semplice polling, ma potrai facilmente usare WebSockets o altre tecnologie.

-
// tutorial14.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox url="/api/comments" pollInterval={2000} />,
-  document.getElementById('content')
-);
-
-

Tutto ciò che abbiamo fatto finora è spostare la chiamata AJAX in un metodo a parte e chiamarlo quando il componente viene caricato per la prima volta e successivamente ogni 2 secondi. Prova ad eseguire questa versione nel tuo browser e a cambiare il file comments.json (si trova nella stessa directory del tuo server); entro 2 secondi i cambiamenti saranno visibili!

-

Aggiungere nuovi commenti #

-

È giunto il momento di costruire il modulo. Il nostro componente CommentForm deve chiedere all'utente il nome e un testo del commento, e inviare una richiesta al server per salvare il commento.

-
// tutorial15.js
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input type="text" placeholder="Il tuo nome" />
-        <input type="text" placeholder="Di' qualcosa..." />
-        <input type="submit" value="Invia" />
-      </form>
-    );
-  }
-});
-
-

Rendiamo il modulo interattivo. Quando l'utente invia il modulo, dobbiamo ripulirlo, inviare una richiesta al server, e aggiornare la lista dei commenti. Per cominciare, ascoltiamo l'evento submit del modulo e ripuliamolo.

-
// tutorial16.js
-var CommentForm = React.createClass({
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
-    var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
-    if (!text || !author) {
-      return;
-    }
-    // TODO: invia la richiesta al server
-    ReactDOM.findDOMNode(this.refs.author).value = '';
-    ReactDOM.findDOMNode(this.refs.text).value = '';
-    return;
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input type="text" placeholder="Il tuo nome" ref="author" />
-        <input type="text" placeholder="Di' qualcosa..." ref="text" />
-        <input type="submit" value="Invia" />
-      </form>
-    );
-  }
-});
-
Eventi #
-

React assegna i gestori degli eventi ai componenti usando una convenzione di nomi camelCased. Assegnamo un gestore onSubmit al modulo in maniera che ripulisca i campi del modulo quando il modulo stesso è inviato con un input valido.

- -

Chiamiamo preventDefault() sull'evento per prevenire l'azione predefinita del browser per l'invio del modulo.

-
Refs #
-

Usiamo l'attributo ref per assegnare un nome a un componente figlio e this.refs per riferirsi al componente. Possiamo chiamare ReactDOM.findDOMNode(component) su di un componente per ottenere l'elemento nativo del DOM del browser.

-
Callback come proprietà #
-

Quando un utente invia un commento, dobbiamo aggiornare la lista dei commenti per includere il nuovo commento. Ha senso posizionare questa logica in CommentBox dal momento che CommentBox possiede lo stato che rappresenta la lista dei commenti.

- -

Dobbiamo passare i dati dal componente figlio su fino al suo genitore. Lo facciamo nel metodo render del nostro genitore passando una nuova callback (handleCommentSubmit) al figlio, legandola all'evento onCommentSubmit del figlio. Quando questo evento viene emesso, la callback verrà eseguita:

-
// tutorial17.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    // TODO: invia al server e aggiorna la lista
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-
-

Chiamiamo la callback da CommentForm quando l'utente invia il modulo:

-
// tutorial18.js
-var CommentForm = React.createClass({
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
-    var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
-    if (!text || !author) {
-      return;
-    }
-    this.props.onCommentSubmit({author: author, text: text});
-    ReactDOM.findDOMNode(this.refs.author).value = '';
-    ReactDOM.findDOMNode(this.refs.text).value = '';
-    return;
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input type="text" placeholder="Il tuo nome" ref="author" />
-        <input type="text" placeholder="Di' qualcosa..." ref="text" />
-        <input type="submit" value="Invia" />
-      </form>
-    );
-  }
-});
-
-

Adesso che le callback sono al loro posto, non ci resta che inviare al server e aggiornare la lista:

-
// tutorial19.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

Ottimizzazione: aggiornamenti ottimistici #

-

La nostra applicazione è adesso completa, ma aspettare che la richiesta completi prima di vedere il commento apparire nella lista la fa sembrare lenta. Possiamo aggiungere ottimisticamente questo commento alla lista per fare apparire l'applicazione più veloce.

-
// tutorial20.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    var comments = this.state.data;
-    var newComments = comments.concat([comment]);
-    this.setState({data: newComments});
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        this.setState({data: comments});
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Commenti</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

Congratulazioni! #

-

Hai appena costruito una casella di commenti in pochi semplici passi. Leggi maggiori dettagli sul perché usare React, o approfondisci la guida di riferimento dell'API e comincia ad hackerare! In bocca al lupo!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tutorial-ja-JP.html b/docs/tutorial-ja-JP.html deleted file mode 100644 index a63ea31fd0..0000000000 --- a/docs/tutorial-ja-JP.html +++ /dev/null @@ -1,1176 +0,0 @@ - - - - - - - チュートリアル | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- チュートリアル -

-
- -

これから、シンプルながらも現実的なコメントボックスを作ってみましょう。ブログにも設置できるようなもので、Disqus や LiveFyre、Facebook comments が採用しているリアルタイムコメントの基本機能を備えたものを想定しています。

- -

その機能とは次のようなものです。

- -
    -
  • コメント全件の表示欄
  • -
  • コメントの送信フォーム
  • -
  • 自作のバックエンドとの連携機能
  • -
- -

ついでに小洒落た機能もいくつか加えましょう。

- -
    -
  • コメントの先読み: 送信したコメントをサーバに保存される前に表示させることで、アプリ動作の体感速度をアップさせます。
  • -
  • 自動更新: 他のユーザのコメントをリアルタイムで表示させます。
  • -
  • Markdown 記法: ユーザが Markdown 記法でコメントを書けるようにします。
  • -
-

全部飛ばしてソースを見たいんだけど? #

-

全部 GitHub にあります。

-

サーバを動かす #

-

このチュートリアルを始めるにあたっては必要ないですが、後半ではサーバに POST を投げる機能を追加します。サーバのことは良く知っていて自分でサーバを建てたいのであれば、それでも構いません。そうではないけれども、サーバサイドは考えずに React のことだけに焦点を絞って学びたい方のため、シンプルなサーバのソースコードを書いておきました。言語は JavaScript (Node.js)または Python、Ruby、Go、ないし PHP で用意してあり、すべて GitHub にあります。ソースを見る ことも出来ますし、 zip ファイルでダウンロードすることも出来ます。

- -

それでは最初のチュートリアルとして、public/index.html の編集から始めましょう。

-

始めてみましょう #

-

このチュートリアルでは、あらかじめビルドされた JavaScript ファイルを CDN から読み込むことになります。自分の好きなエディタを立ち上げて、次のように新規の HTML ドキュメントを作りましょう。

-
<!-- index.html -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>React Tutorial</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-    <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-    <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-
-  </head>
-  <body>
-    <div id="content"></div>
-    <script type="text/babel">
-      // ここにコードが入ります
-    </script>
-  </body>
-</html>
-
-

このチュートリアルに関しては、JavaScript コードを script タグの中へ書いていくことにします。

- -
-

確認:

- -

上のコードで jQuery を読み込んでいますが、これはチュートリアル後半で ajax のコードを簡潔に書きたいだけなので、React を動かすのに必要なものではありません

-
-

最初のコンポーネント #

-

React はすべて、モジュール単位で組み立てられる(composable)コンポーネントからなっています。今回取り上げるコメントボックスの例では、以下のようなコンポーネント構造をとります。

-
- CommentBox
-  - CommentList
-    - Comment
-  - CommentForm
-
-

それではまず CommentBox コンポーネントから作っていきましょう。とは言っても単なる <div> です。

-
// tutorial1.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        Hello, world! I am a CommentBox.
-      </div>
-    );
-  }
-});
-ReactDOM.render(
-  <CommentBox />,
-  document.getElementById('content')
-);
-

JSX シンタックス #

-

先程書いた JavaScript の中に、XMLに似たシンタックスがあることに気付いたでしょうか。このシンタックスシュガーは、シンプルなプリコンパイラによって次のような生の JavaScript に変換されます。

-
// tutorial1-raw.js
-var CommentBox = React.createClass({displayName: 'CommentBox',
-  render: function() {
-    return (
-      React.createElement('div', {className: "commentBox"},
-        "Hello, world! I am a CommentBox."
-      )
-    );
-  }
-});
-ReactDOM.render(
-  React.createElement(CommentBox, null),
-  document.getElementById('content')
-);
-
-

どちらを採るかは自由ですが、生の JavaScript よりも JSX シンタックスのほうが扱いやすいと考えています。詳しくは JSX シンタックスの記事 を読んでみてください。

-

何をしているのか #

-

先程のコードでは、とあるメソッドを持った JavaScript オブジェクトを React.createClass() に渡しています。これは新しい React コンポーネントを作るためです。このメソッドは render と呼ばれており、最終的に HTML へレンダリングされる React コンポーネントのツリーを返す点が肝になります。

- -

コードに書いた <div> タグは実際の DOM ノードではありません。これは React の div コンポーネントのインスタンスです。 これらは React が理解できるマーカーやデータの一部だと見なせます。React は 安全 です。デフォルトで XSS 対策を行っているので、HTML 文字列を生成することはありません。

- -

実際の HTML を返す必要はありません。 自分が(もしくは他の誰かが)組み立てたコンポーネントツリーを返せばいいのです。 これこそ React が composableな(組み立てられる)ものである理由であり、この大事なルールを守ればフロントエンドはメンテナンスしやすいものとなります。

- -

ReactDOM.render() はまずルートコンポーネントのインスタンスを作り、フレームワークを立ち上げます。そして、第2引数で与えられた実際の DOM 要素にマークアップを挿入します。

-

コンポーネントの組み立て #

-

それでは CommentListCommentForm の骨組みを作りましょう。繰り返しになりますが、これらはただの <div> です。

-
// tutorial2.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        Hello, world! I am a CommentList.
-      </div>
-    );
-  }
-});
-
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <div className="commentForm">
-        Hello, world! I am a CommentForm.
-      </div>
-    );
-  }
-});
-
-

さて、この新しいコンポーネントを使えるように CommentBox コンポーネントを書き直しましょう。

-
// tutorial3.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

ここで、HTML タグと組み立てているコンポーネントが、どのようにミックスされているかを確認しましょう。 HTML コンポーネントは既定の React コンポーネントですが、自分で定義したもの同士はそれぞれ別物になります。JSX コンパイラは HTML タグを自動的に React.createElement(tagName) の式に書き換え、それぞれを別々のものに変換します。これはグローバルの名前空間が汚染させるのを防ぐためです。

-

Props を使う #

-

次のステップは Comment コンポーネントの作成です。このコンポーネントは、自分の親にあたるコンポーネントから渡されたデータを扱います。親から渡されたデータは、子のコンポーネントで「プロパティ」として利用できます。この「プロパティ」には this.props を通してアクセスします。props(プロパティ)を使うと CommentList から Comment に渡されたデータの読み込み、マークアップのレンダリングが可能になります。

-
// tutorial4.js
-var Comment = React.createClass({
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {this.props.children}
-      </div>
-    );
-  }
-});
-
-

JSX の内側で(属性値または子要素として)JavaScript の式を波括弧で囲むと、テキストや React コンポーネントをツリーに加えることが出来ます。コンポーネントに渡された属性値には名前が付けられており、this.props をキーとしてアクセスできます。また、ネストされた子要素の値は this.props.children でアクセスが可能です。

-

コンポーネントのプロパティ #

-

さて、これまでに Comment コンポーネントを定義しました。これからこのコンポーネントに、コメントの著者名と内容を渡せるようにします。これを実装することで、それぞれ別のコメントに対して同じコードを使い回せるようになります。それでは早速 CommentList の中にコメントを追加していきましょう。

-
// tutorial5.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        <Comment author="Pete Hunt">This is one comment</Comment>
-        <Comment author="Jordan Walke">This is *another* comment</Comment>
-      </div>
-    );
-  }
-});
-
-

ここで確認してもらいたいのは、親の CommentList コンポーネントから、子の Comment コンポーネントにデータが渡されている点です。この例ではまず、Pete Hunt(属性値を通して)と This is one comment(XML のような子ノードを通して)といったデータを Comment コンポーネントに渡しています。少し前に確認した通り、Comment コンポーネントからこれらの「プロパティ」にアクセスするには、this.props.authorthis.props.children を使います。

-

Markdown の追加 #

-

Markdown はインラインでテキストをフォーマットする簡単な記法です。例えば、テキストをアスタリスクで挟むと強調されて表示されます。

- -

まず最初に、サードパーティ製の remarkable ライブラリをアプリケーションに追加します。 remarkable は Markdown テキストを生の HTML に変換する JavaScript ライブラリです。 既にある head タグの内側に script タグを書き込み、以下のように remarkable を読み込ませます。

-
<!-- index.html -->
-<head>
-  <meta charset="UTF-8" />
-  <title>Hello React</title>
-  <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-  <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-  <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-  <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-</head>
-
-

次に、Markdown で書かれたコメントを変換して出力してみましょう。

-
// tutorial6.js
-var Comment = React.createClass({
-  render: function() {
-    var md = new Remarkable();
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {md.render(this.props.children.toString())}
-      </div>
-    );
-  }
-});
-
-

このコードでは remarkable のライブラリを呼び出すことしかしていません。this.props.children は React によってラップされたテキストですが、これを remarkable が理解できる生の文字列に変換する必要があります。そのため、上のコードでは明示的に toString() を呼び出しているのです。

- -

しかし問題があります!ブラウザがレンダリングしたコメントは次のように表示されているはずです -- "<p>This is <em>another</em> comment</p>" このようなタグは実際に HTML としてレンダリングさせたいですね。

- -

このような現象が起きるのは React が XSS 攻撃に対する防御を行っているからです。これを回避する方法はありますが、それを使うときにはフレームワークが警告をします。

-
// tutorial7.js
-var Comment = React.createClass({
-  rawMarkup: function() {
-    var md = new Remarkable();
-    var rawMarkup = md.render(this.props.children.toString());
-    return { __html: rawMarkup };
-  },
-
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        <span dangerouslySetInnerHTML={this.rawMarkup()} />
-      </div>
-    );
-  }
-});
-
-

これは特別な API であり、生の HTML が挿入されにくくなるよう意図的に作ったものです。しかし、ここでは remarkable のためにこのバックドアを利用しています。

- -

注意: この機能を使うことで、remarkable は安全なものと信頼することになります。

-

データモデルとの連携 #

-

これまではソースコードにコメントを直に書き込んでいました。その代わりに、これからは JSON の blob データをコメントリストにレンダリングしてみましょう。サーバからデータを取得するのが最後の目標ですが、とりあえず今はソースコードの中にデータを書いておくことにします。

-
// tutorial8.js
-var data = [
-  {id: 1, author: "Pete Hunt", text: "This is one comment"},
-  {id: 2, author: "Jordan Walke", text: "This is *another* comment"}
-];
-
-

このデータはモジュールを使って CommentList に取り込む必要があります。CommentBoxReactDOM.render() の部分を手直しして、props を通してデータが CommentList へ渡るようにしましょう。

-
// tutorial9.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.props.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox data={data} />,
-  document.getElementById('content')
-);
-
-

こうして CommentList がデータを扱えるようになりました。それでは、コメントを動的にレンダリングしてみましょう。

-
// tutorial10.js
-var CommentList = React.createClass({
-  render: function() {
-    var commentNodes = this.props.data.map(function (comment) {
-      return (
-        <Comment author={comment.author} key={comment.id}>
-          {comment.text}
-        </Comment>
-      );
-    });
-    return (
-      <div className="commentList">
-        {commentNodes}
-      </div>
-    );
-  }
-});
-
-

これだけ!

-

サーバからのデータの取得 #

-

続いて、ハードコーディングしていたデータを、サーバからの動的なデータに置き換えてみましょう。

-
// tutorial11.js
-ReactDOM.render(
-  <CommentBox url="/api/comments" />,
-  document.getElementById('content')
-);
-
-

このコンポーネントは自身を再びレンダリングすることになるので、これまでのコンポーネントとは異なります。レスポンスがサーバから返ってくると、送られてきた新しいコメントをコンポーネントがレンダリングすることになります。ですが、その時点までコンポーネントには何もデータがないはずです。

- -

確認: 上のコードは、このステップではまだ動きません。

-

Reactive state #

-

これまで、それぞれのコンポーネントは自身の props の値を用いて、一度だけレンダリングしていました。props はイミュータブルです。つまり、props は親から渡されますが、同時に props は親の「所有物」なのです。データが相互にやり取りされるのを実現するため、ここでミュータブルな state(状態)をコンポーネントに取り入れましょう。コンポーネントは this.state というプライベートな値を持ち、this.setState() を呼び出すことで state を更新することが出来ます。コンポーネントの state が更新されれば、そのコンポーネントは自身を再びレンダリングし直します。

- -

render() メソッドは this.propsthis.state と同じく宣言的に書かれています。このフレームワークによって、UI と入力が常に一致するようになります。

- -

サーバがデータを集めてくれば、今あるコメントのデータを更新することになるかもしれません。state を表すコメントのデータの配列を CommentBox コンポーネントに加えましょう。

-
// tutorial12.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

getInitialState() メソッドはコンポーネントのライフサイクル内で一回だけ実行され、コンポーネントの state における初期値を設定します。

-

State の更新 #

-

コンポーネントの作成と同時に、サーバから JSON データを GET で取得し、state を更新して最新のデータを反映させてみましょう。実際のアプリケーションでは動的なエンドポイントになるでしょうが、今回の例では話を簡単にするため、以下の静的な JSON ファイルを使います。

-
[
-  {"id": "1", "author": "Pete Hunt", "text": "This is one comment"},
-  {"id": "2", "author": "Jordan Walke", "text": "This is *another* comment"}
-]
-
-

サーバへの非同期リクエストを作るため、ここでは jQuery を使います。

- -

注意: ここからは AJAX アプリケーションを作っていくので、自分のファイルシステム上ではなく Web サーバを使ってアプリを作る必要があります。残りのチュートリアルに必要な機能は 冒頭で紹介した サーバに含まれています。ソースコードは GitHub に用意してあります。

-
// tutorial13.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

さて、componentDidMount はコンポーネントがレンダリングされたときに React が自動的に呼び出すメソッドです。動的な更新の鍵となるのは this.setState() の呼び出し方です。ここでは、古いコメントの配列をサーバから取ってきた新しい配列に置き換え、UI を自動的に更新させてみましょう。このような reactivity(反応性・柔軟性)のおかげで、リアルタイム更新を最小限にすることが出来ます。次のコードではシンプルなポーリングをしていますが、WebSockets や他の方法でも簡単に実現できます。

-
// tutorial14.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox url="/api/comments" pollInterval={2000} />,
-  document.getElementById('content')
-);
-
-

ここまでに、AJAX を呼び出す部分を別のメソッド内に移動させました。加えて、コンポーネントが最初に読み込まれてから2秒ごとに AJAX のメソッドが呼び出されるようにしました。ぜひ自分のブラウザで実行させて、comments.json ファイルに変更を加えてみてください。2秒以内に表示が更新されるはずです!

-

新しいコメントの追加 #

-

いよいよフォームを作る段階に来ました。ここで CommentForm コンポーネントは、ユーザに自分の名前とコメントの内容を入力させ、コメントを保存するためにサーバにリクエストを送信する必要があります。

-
// tutorial15.js
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input type="text" placeholder="Your name" />
-        <input type="text" placeholder="Say something..." />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-

制御コンポーネント #

-

このチュートリアルの DOM は、input 要素がレンダリングされ、ブラウザが状態(そのレンダリングされた値)を管理します。その結果、実際のDOMの状態がコンポーネントとは異なります。ビューの状態がコンポーネントとは異なり、これは理想的ではありません。React では、コンポーネントは初期化の時点だけでなく、常にビューの状態を表している必要があります。

- -

したがって、ユーザの入力を保存するために this.state を使用することになります。2つのプロパティのauthortextに最初のstateを定義して、空の文字列を設定します。<input>の要素では、onChangeにハンドラをアタッチするとvaluestate が反映される。これらの <input> の要素は、value が設定された制御コンポーネントと呼ばれています。制御コンポーネントの詳細についてはこちらのForms articleをご覧ください。

-
// tutorial16.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-

イベント #

-

React イベントハンドラのアタッチはコンポーネントにキャメルケースの命名規則を使用します。2つの<input>要素にonChangeのハンドラをアタッチします。今、ユーザーの入力は<input>フィールド、アタッチされたonChangeがコールバックされてコンポーネントのstateが変更されます。その後、input要素のレンダリングされた値は、現在のコンポーネントstateを反映するように更新されます。

- -

(賢明な読者は、説明したようにこれらのイベントハンドラが動作することを驚かれるかもしれない、明示的な結合を不要にそのコンポーネントインスタンスへの各メソッドは、メソッドの参照が明示的にthis. React.createClass(...) automatically bindsにバインドされていないことを自動的に結合する与えられました。)

-

フォーム送信 #

-

フォームを対話型にしましょう。ユーザーがフォームを送信すると、それをクリアする必要があります。サーバに要求を送信すると、コメントのリストを更新します。開始するとフォームの送信イベントでクリアするか試しましょう。

-
// tutorial17.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.state.author.trim();
-    var text = this.state.text.trim();
-    if (!text || !author) {
-      return;
-    }
-    // TODO: サーバーに要求を送信
-    this.setState({author: '', text: ''});
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-
-

フォームが有効な入力でサブミットされたときにフォームフィールドをクリアし、フォームにonSubmitハンドラをアタッチします。

- -

preventDefault() はフォームを送信するイベントにブラウザのデフォルトのアクションを防ぐためにコールします。

-

Props としてのコールバック #

-

ユーザがコメントを送信したら、コメントリストをリフレッシュして新しいリストを読み込むことになります。コメントリストを表す state を保持しているのは CommentBox なので、必要なロジックは CommentBox の中に書くのが筋でしょう。

- -

ここでは子のコンポーネントから親に向かって、いつもとは逆方向にデータを返す必要があります。まず、親のコンポーネントに新しいコールバック関数(handleCommentSubmit)を定義します。続いて render メソッド内にある子のコンポーネントにコールバックを渡すことで、onCommentSubmit イベントとコールバックを結び付けています。こうすることで、イベントが発生するたびにコールバックが呼び出されます。

-
// tutorial18.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    // TODO: submit to the server and refresh the list
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-
-

今、CommentBoxonCommentSubmitをpropしてCommentFormにコールバックを利用した、ユーザーがフォームを送信したときにCommentFormはコールバックを呼び出すことができます。

-
// tutorial19.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.state.author.trim();
-    var text = this.state.text.trim();
-    if (!text || !author) {
-      return;
-    }
-    this.props.onCommentSubmit({author: author, text: text});
-    this.setState({author: '', text: ''});
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-
-

こうしてコールバックが出来たので、あとはサーバにコメントを送信してリストをリフレッシュすれば完璧です。

-
// tutorial20.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

最適化: 先読み更新 #

-

アプリケーションに必要な機能は一通り実装できました。しかし、フォームからコメントを送信しても、サーバからのレスポンスが来るまで自分のコメントはリストに載らないため、アプリの動作は遅く感じます。ここでは、送信したコメントをリストに先読みさせて、アプリの体感速度をアップさせましょう。

-
// tutorial21.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    var comments = this.state.data;
-    // Optimistically set an id on the new comment. It will be replaced by an
-    // id generated by the server. In a production application you would likely
-    // not use Date.now() for this and would have a more robust system in place.
-    comment.id = Date.now();
-    var newComments = comments.concat([comment]);
-    this.setState({data: newComments});
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        this.setState({data: comments});
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

おめでとう! #

-

シンプルな手順を追ううちにコメントボックスを作ることが出来ました。さらに詳しいことはなぜ React を使うのかを読んだり、API リファレンスを開いたりしてハッキングを始めましょう!幸運を祈ります!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tutorial-ko-KR.html b/docs/tutorial-ko-KR.html deleted file mode 100644 index c1524be3c5..0000000000 --- a/docs/tutorial-ko-KR.html +++ /dev/null @@ -1,1102 +0,0 @@ - - - - - - - 튜토리얼 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 튜토리얼 -

-
- -

블로그에 붙일만한 간단하지만 실용적인 댓글상자를 만들어 볼 것입니다. Disqus, LiveFyre, Facebook에서 제공하는 것 같은 실시간 댓글의 간단한 버전이죠.

- -

이런 기능을 넣겠습니다:

- -
    -
  • 댓글목록
  • -
  • 댓글작성폼
  • -
  • 커스텀 백엔드를 위한 Hooks
  • -
- -

멋진 기능도 조금 넣어보겠습니다:

- -
    -
  • 낙관적 댓글 달기: 댓글은 서버에 저장되기도 전에 목록에 나타납니다. 그래서 빠르게 느껴집니다.
  • -
  • 실시간 업데이트: 다른 사용자가 남기는 댓글이 실시간으로 나타납니다.
  • -
  • Markdown 지원: 사용자는 글을 꾸미기 위해 Markdown 형식을 사용할 수 있습니다.
  • -
-

그냥 다 생략하고 소스만 보고 싶나요? #

-

GitHub에 전부 있습니다.

-

서버 구동하기 #

-

이 튜토리얼을 시작하기 위해, 서버를 구동할 필요가 있습니다. 이 서버는 순수하게 우리가 받고 저장할 데이터의 API 엔드포인트로써만 사용합니다. 이를 가능한한 쉽게하기 위해, 필요한 것만 제공하는 간단한 서버를 몇가지 스크립트 언어로 만들었습니다. 시작하는데 필요한 모든 것이 들어있는 소스를 보시거나 zip 파일을 다운로드 할 수 있습니다.

- -

단순하게 하기위해, 서버는 JSON 파일을 데이터베이스로 사용합니다. 프로덕션에서 사용할 수는 없지만 이렇게 하면 API를 사용할 때 시뮬레이션이 단순해집니다. 서버가 시작되면, API 엔드포인트를 제공하고 필요한 정적 페이지를 서빙합니다.

-

시작하기 #

-

이 튜토리얼에서는 가능한한 간단하게 만들겠습니다. 위에서 언급된 서버 패키지에 우리가 작업할 HTML 파일 포함되어 있습니다. 편한 편집기에서 public/index.html를 여세요. 이는 이런 내용이어야 합니다.(아마 조금 다를 수 있습니다만, 여기에 나중에 <script> 태그를 추가 할 것입니다.)

-
<!-- index.html -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8" />
-    <title>React Tutorial</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-    <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-    <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-  </head>
-  <body>
-    <div id="content"></div>
-    <script type="text/babel" src="scripts/example.js"></script>
-    <script type="text/babel">
-      // 이 튜토리얼을 시작하려면, 그냥 scripts/example.js를 로드하는 스크립트
-      // 태그를 제거하고 여기에 코드를 적으세요.
-    </script>
-  </body>
-</html>
-
-

다음 진행을 위해, 위의 스크립트 태그안에 JavaScript 코드를 작성합니다. (이 튜토리얼에서는) 진보된 라이브 리로드가 없기 때문에, 수정 사항을 저장한 다음에는 브라우저를 새로고침해서 확인해야 합니다. 서버를 시작한 다음 브라우저에서 http://localhost:3000를 열어 따라해 보세요. 아무런 수정도 하지 않았다면, 최초 로드시 우리가 만들 제품의 완성품을 확인할 수 있을 것입니다. 작업할 준비가 되면, 이전의 <script> 태그를 삭제하고 진행하세요.

- -
-

주의:

- -

여기서는 ajax 요청 코드를 단순화 하기 위해 jQuery를 넣었지만, 이는 React의 동작에 필수적인 것은 아닙니다.

-
-

첫 번째 컴포넌트 #

-

모듈화 된, 조합가능한 컴포넌트가 React의 전부입니다. 댓글상자 예제에서 우리는 다음과 같은 컴포넌트 구조를 가질 것입니다:

-
- CommentBox
-  - CommentList
-    - Comment
-  - CommentForm
-
-

자, 이제 CommentBox 컴포넌트를 만들어 봅시다. <div> 하나로 구성되어 있습니다.

-
// tutorial1.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        Hello, world! I am a CommentBox.
-      </div>
-    );
-  }
-});
-ReactDOM.render(
-  <CommentBox />,
-  document.getElementById('content')
-);
-
-

네이티브 HTML 엘리먼트 이름은 소문자로 시작하고 커스텀 React 클래스 이름은 대문자로 시작합니다.

-

JSX 문법 #

-

JavsScript 안의 유사 XML 구문이 먼저 눈에 띌 것입니다. 우리에겐 이를 JavaScript로 변환해주는 간단한 프리컴파일러(precompiler)가 있습니다.

-
// tutorial1-raw.js
-var CommentBox = React.createClass({displayName: 'CommentBox',
-  render: function() {
-    return (
-      React.createElement('div', {className: "commentBox"},
-        "Hello, world! I am a CommentBox."
-      )
-    );
-  }
-});
-ReactDOM.render(
-  React.createElement(CommentBox, null),
-  document.getElementById('content')
-);
-
-

JSX의 사용은 선택적이지만 JSX 문법이 일반 JavsScript보다 사용하기 쉽습니다. JSX 문법 문서에서 더 알아보세요.

-

무슨 일이 일어나고 있는가 #

-

우리는 새로운 React 컴포넌트를 만들기 위해 React.createClass()로 JavaScript 객체에 몇 개의 메소드를 담아 넘겼습니다. 이 중 가장 중요한것은 render 메소드인데, 이는 React 컴포넌트 트리를 리턴해서 최종적으로 실제 HTML을 그려주게 됩니다.

- -

<div> 태그들은 실제 DOM 노드가 아니라 React div 컴포넌트의 인스턴스입니다. 이것은 React가 다룰 수 있는 데이터의 표시자(markers)나 조각이라 생각하셔도 됩니다. React는 안전합니다. 생(raw) HTML 문자열을 생성하는 것이 아니기 때문에 XSS을 기본적으로 방지합니다.

- -

일반적인 HTML만 리턴할 수 있는 것은 아닙니다. 여러분이 직접 만든 (또는 다른 사람들이 만들어 놓은) 컴포넌트의 트리를 리턴할 수도 있습니다. 이것이 React를 조합가능(composable)하게 만듭니다: 유지보수 가능한 프론트엔드를 위한 핵심 교리(key tenet)지요.

- -

ReactDOM.render()는 최상위 컴포넌트의 인스턴스를 만들고, 두 번째 인수로 전달받은 DOM 엘리먼트에 마크업을 삽입해 프레임워크를 시작합니다.

- -

ReactDOM 모듈은 DOM 특정 메소드를 노출해, React가 코어 툴을 다른 플렛폼(예를 들어, React Native)에 공유할 수 있게 합니다.

-

컴포넌트 조합하기 #

-

이제 CommentListCommentForm을 위한 뼈대를 구축해 봅시다. 이전과 마찬가지로 단순히 <div> 태그 하나 입니다. 파일에 두 컴포넌트를 추가해, 이미 있는 CommentBox 선언을 참고로 ReactDOM.render를 호출합시다.

-
// tutorial2.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        안녕!  댓글목록이야.
-      </div>
-    );
-  }
-});
-
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <div className="commentForm">
-        안녕!  댓글 폼이야.
-      </div>
-    );
-  }
-});
-
-

다음은 CommentBox 컴포넌트가 새로 만든 컴포넌트들을 사용하도록 수정합니다.

-
// tutorial3.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

방금 만든 컴포넌트들을 어떻게 HTML 태그들과 섞어 사용하는지 살펴보세요. HTML 컴포넌트들도 한가지 차이만 제외한다면 우리가 정의한 것과 같은 표준적인 React 컴포넌트입니다. JSX 컴파일러가 자동으로 HTML 태그들을 React.createElement(tagName) 표현식으로 재작성하고 나머지는 그대로 둘 것입니다. 이는 전역 네임스페이스가 오염되는 것을 막아줍니다.

-

props 사용하기 #

-

부모로 부터 받은 데이터에 의존하는 Comment 컴포넌트를 만들어 봅시다. 부모 컴포넌트로 부터 받은 데이터는 자식 컴포넌트에서 '프로퍼티'로 사용가능 합니다. 이 '프로퍼티들'은 this.props를 통해 접근합니다. props를 사용해, CommentList에서 전달받은 데이터를 읽어들이고, 마크업을 렌더할 수 있을 것입니다.

-
// tutorial4.js
-var Comment = React.createClass({
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {this.props.children}
-      </div>
-    );
-  }
-});
-
-

JSX 내부의 중괄호로 둘러싸인 JavaScript 표현식(어트리뷰트나 엘리먼트의 자식으로 사용된)을 통해 텍스트나 React 컴포넌트를 트리에 더할 수 있습니다. this.props를 통해 컴포넌트에 전달된 특정한 어트리뷰트들에, this.props.children을 통해 중첩된 엘리먼트들에 접근할 수 있습니다.

-

컴포넌트 프로퍼티 (Component Properties) #

-

Comment 컴포넌트를 만들었으니, 여기에 글쓴이와 내용을 넘겨보도록 합시다. 이렇게 함으로써 각 고유한 comment에서 같은 코드를 재사용할 수 있습니다. 먼저 댓글 몇 개를 CommentList에 추가해 봅시다:

-
// tutorial5.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        <Comment author="Pete Hunt">댓글입니다</Comment>
-        <Comment author="Jordan Walke">* 다른* 댓글입니다</Comment>
-      </div>
-    );
-  }
-});
-
-

부모 컴포넌트인 CommentList에서 자식 컴포넌트인 Comment에 데이터들을 전달하고 있는것을 확인할 수 있습니다. 예를 들어, 우리는 어트리뷰트로 Pete Hunt를, XML 형식의 자식 노드로 댓글입니다를 첫 번째 Comment로 넘겼습니다. 위에서 언급했듯이 Comment 컴포넌트는 그들의 '프로퍼티'를 this.props.author, this.props.children를 통해 접근합니다.

-

Markdown 추가하기 #

-

Markdown은 텍스트를 포맷팅하는 간단한 방식입니다. 예를 들어, 별표(*)로 텍스트를 둘러싸는 것은 강조의 의미입니다.

- -

먼저 서드파티 라이브러리인 remarkable를 애플리케이션에 추가합니다. 이 JavaScript 라이브러리는 Markdown 텍스트를 HTML 문법으로 변환해줍니다. head 태그안에 스크립트 태그를 추가해 주세요. (React playground에는 이미 포함되어 있습니다):

-
<!-- index.html -->
-<head>
-  <meta charset="utf-8" />
-  <title>React Tutorial</title>
-  <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-  <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-  <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-  <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-  <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-</head>
-
-

다음은, 댓글 텍스트를 Markdown으로 전환하고 출력해 봅시다.

-
// tutorial6.js
-var Comment = React.createClass({
-  render: function() {
-    var md = new Remarkable();
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {md.render(this.props.children.toString())}
-      </div>
-    );
-  }
-});
-
-

우리가 한 일이라고는 remarkable 라이브러리를 호출한 것 뿐입니다. remarkable가 this.props.children에서 텍스트를 읽어들여 처리할 수 있도록 React 형식의 텍스트(React's wrapped text)를 단순 텍스트(raw string)으로 전환하기 위해 명시적으로 toString()을 호출했습니다.

- -

하지만 여기엔 문제가 있습니다! 우리는 HTML 태그들이 정상적으로 렌더되길 원하지만 브라우저에 출력된 결과물은 "<p><em>또 다른</em> 댓글입니다</p>"처럼 태그가 그대로 보일것입니다.

- -

React는 이런 식으로 XSS 공격을 예방합니다. 우회할 방법이 있긴 하지만 프레임워크는 사용하지 않도록 경고하고 있습니다:

-
// tutorial7.js
-var Comment = React.createClass({
-  rawMarkup: function() {
-    var md = new Remarkable();
-    var rawMarkup = md.render(this.props.children.toString());
-    return { __html: rawMarkup };
-  },
-
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        <span dangerouslySetInnerHTML={this.rawMarkup()} />
-      </div>
-    );
-  }
-});
-
-

이는 의도적으로 생(raw) HTML을 넣기 힘들게 하려고 만든 특별한 API지만 remarkable를 사용하기 위해 이 백도어를 활용합시다.

- -

잊지 마세요: 이 기능은 remarkable가 안전한 것으로 믿고 사용하는 것입니다.

-

데이터 모델 연결하기 #

-

지금까지는 소스코드에 직접 댓글을 넣었습니다. 이제부터는 JSON 데이터 덩어리를 댓글 목록에 렌더해보겠습니다. 최종적으로는 서버에서 데이터가 내려오겠지만, 지금은 소스에 직접 데이터를 넣어봅시다:

-
// tutorial8.js
-var data = [
-  {author: "Pete Hunt", text: "댓글입니다"},
-  {author: "Jordan Walke", text: "*또 다른* 댓글입니다"}
-];
-
-

이 데이터를 모듈화된 방식으로 CommentList에 넣어야 합니다. props을 이용해 데이터를 넘기도록 CommentBoxReactDOM.render() 호출 코드를 수정합시다.

-
// tutorial9.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList data={this.props.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox data={data} />,
-  document.getElementById('content')
-);
-
-

이제 CommentList에서 데이터를 다룰 수 있습니다. 댓글을 동적으로 렌더해봅시다:

-
// tutorial10.js
-var CommentList = React.createClass({
-  render: function() {
-    var commentNodes = this.props.data.map(function (comment) {
-      return (
-        <Comment author={comment.author} key={comment.id}>
-          {comment.text}
-        </Comment>
-      );
-    });
-    return (
-      <div className="commentList">
-        {commentNodes}
-      </div>
-    );
-  }
-});
-
-

이게 전부입니다!

-

서버에서 가져오기(Fetching) #

-

이제 데이터를 소스에 직접 넣는 방식에서 서버에서 동적으로 받아서 처리하는 방식으로 바꿔봅시다. 데이터 prop을 삭제하고 처리할 URL로 변경해 줍시다.

-
// tutorial11.js
-ReactDOM.render(
-  <CommentBox url="/api/comments" />,
-  document.getElementById('content')
-);
-
-

이 컴포넌트는 이전 것과 다르게, 스스로 다시 렌더링해야 합니다. 컴포넌트는 서버에서 요청이 들어올때까지는 아무 데이터도 가지고 있지 않다가, 특정한 시점에서 새로운 댓글을 렌더할 필요가 있을 것입니다.

- -

주의: 이 단계에서 코드는 아직 동작하지 않습니다.

-

반응적 state #

-

지금까지, 각각의 컴포넌트는 props를 기반으로 한번 렌더되었습니다. props는 불변성을 갖습니다: 그것들은 부모에서 전달되어 부모에게 "소유" 되어 있습니다. 컴포넌트에 상호작용을 구현하기 위해서, 가변성을 갖는 state를 소개합니다. this.state는 컴포넌트에 한정(private)되며 this.setState()를 통해 변경할 수 있습니다. state가 업데이트 되면, 컴포넌트는 자신을 스스로 다시 렌더링합니다.

- -

render() 메소드는 this.propsthis.state를 위한 함수로 선언적으로 작성됩니다. 프레임워크에서 입력값에 따른 UI가 항상 일관성 있음을 보장해줍니다.

- -

서버가 데이터를 가져오면 댓글 데이터가 변경될 것입니다. 댓글 데이터의 배열을 CommentBox의 state로 추가해봅시다:

-
// tutorial12.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

getInitialState() 는 컴포넌트의 생명주기동안 한 번만 실행되며 컴포넌트의 초기 state를 설정합니다.

-

state 업데이트하기 #

-

컴포넌트의 최초 생성 시에, 서버에서 GET 방식으로 JSON을 넘겨받아 최신의 데이터가 state에 반영되길 원했습니다. jQuery를 사용해 서버에 비동기 요청을 만들어 필요한 데이터를 빨리 가져올 수 있게 하겠습니다. 이런 식입니다.

-
[
-  {"author": "Pete Hunt", "text": "댓글입니다"},
-  {"author": "Jordan Walke", "text": "*또 다른* 댓글입니다"}
-]
-
// tutorial13.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

여기서 componentDidMount는 컴포넌트가 렌더링 된 다음 React에 의해 자동으로 호출되는 메소드입니다. 동적 업데이트의 핵심은 this.setState()의 호출입니다. 우리가 이전의 댓글 목록을 서버에서 넘어온 새로운 목록으로 변경하면 자동으로 UI가 업데이트 될 것입니다. 이 반응성 덕분에 실시간 업데이트에 아주 작은 수정만 가해집니다. 우리는 여기선 간단한 폴링을 사용할 것이지만 웹소켓등의 다른 기술도 쉽게 사용할 수 있습니다.

-
// tutorial14.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox url="/api/comments" pollInterval={2000} />,
-  document.getElementById('content')
-);
-
-

우리가 여기서 한것은 AJAX 호출을 별도의 메소드로 분리하고 컴포넌트가 처음 로드된 시점부터 2초 간격으로 계속 호출되도록 한 것입니다. 브라우저에서 직접 돌려보고 comments.json 파일(서버의 같은 디렉토리에 있습니다)을 수정해보세요. 2초 간격으로 변화되는 모습이 보일 것입니다!

-

새로운 댓글 추가하기 #

-

이제 폼을 만들어볼 시간입니다. 우리의 CommentForm 컴포넌트는 사용자에게 이름과 내용을 입력받고 댓글을 저장하기 위해 서버에 요청을 전송해야 합니다.

-
// tutorial15.js
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input type="text" placeholder="이름" />
-        <input type="text" placeholder="내용을 입력하세요..." />
-        <input type="submit" value="올리기" />
-      </form>
-    );
-  }
-});
-
-

이제 폼의 상호작용을 만들어 보겠습니다. 사용자가 폼을 전송하는 시점에 우리는 폼을 초기화하고 서버에 요청을 전송하고 댓글목록을 업데이트해야 합니다. 폼의 submit 이벤트를 감시하고 초기화 해주는 부분부터 시작해 보죠.

-
// tutorial16.js
-var CommentForm = React.createClass({
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.refs.author.value.trim();
-    var text = this.refs.text.value.trim();
-    if (!text || !author) {
-      return;
-    }
-    // TODO: 서버에 요청을 전송합니다
-    this.refs.author.value = '';
-    this.refs.text.value = '';
-    return;
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input type="text" placeholder="이름" ref="author" />
-        <input type="text" placeholder="내용을 입력하세요..." ref="text" />
-        <input type="submit" value="올리기" />
-      </form>
-    );
-  }
-});
-
이벤트 #
-

React는 카멜케이스 네이밍 컨벤션으로 컴포넌트에 이벤트 핸들러를 등록합니다. 폼이 유효한 값으로 submit되었을 때 폼필드들을 초기화하도록 onSubmit 핸들러를 등록합니다.

- -

폼 submit에 대한 브라우저의 기본동작을 막기 위해 이벤트시점에 preventDefault()를 호출합니다.

-
Refs #
-

자식 컴포넌트의 이름을 지정하기 위해 ref 어트리뷰트를, DOM 노드를 참조하기 위해 this.refs를 사용합니다.

-
props으로 콜백 처리하기 #
-

사용자가 댓글을 등록할 때, 새로운 댓글을 추가하기 위해 댓글목록을 업데이트해주어야 합니다. CommentBox가 댓글목록의 state를 소유하고 있기 때문에 이 로직 또한 CommentBox에 있는것이 타당합니다.

- -

자식 컴포넌트가 그의 부모에게 데이터를 넘겨줄 필요가 있습니다. 부모의 render 메소드에서 새로운 콜백(handleCommentSubmit)을 자식에게 넘겨주고, 자식의 onCommentSubmit 이벤트에 그것을 바인딩해주는 식으로 구현합니다. 이벤트가 작동될때(triggered)마다, 콜백이 호출됩니다:

-
// tutorial17.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    // TODO: 서버에 요청을 수행하고 목록을 업데이트한다
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-
-

사용자가 폼을 전송할 때, CommentForm에서 콜백을 호출해 봅시다:

-
// tutorial18.js
-var CommentForm = React.createClass({
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.refs.author.value.trim();
-    var text = this.refs.text.value.trim();
-    if (!text || !author) {
-      return;
-    }
-    this.props.onCommentSubmit({author: author, text: text});
-    this.refs.author.value = '';
-    this.refs.text.value = '';
-    return;
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input type="text" placeholder="이름" ref="author" />
-        <input type="text" placeholder="이름을 입력하세요..." ref="text" />
-        <input type="submit" value="올리기" />
-      </form>
-    );
-  }
-});
-
-

이제 콜백이 제자리를 찾았습니다. 우리가 할 일은 서버에 요청을 날리고 목록을 업데이트하는 것 뿐입니다:

-
// tutorial19.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

최적화: 낙관적 업데이트 #

-

우리의 애플리케이션은 이제 모든 기능을 갖추었습니다. 하지만 댓글이 목록에 업데이트되기 전에 완료요청을 기다리는 게 조금 느린듯한 느낌이 드네요. 우리는 낙관적 업데이트를 통해 댓글이 목록에 추가되도록 함으로써 앱이 좀 더 빨라진 것처럼 느껴지도록 할 수 있습니다.

-
// tutorial20.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    var comments = this.state.data;
-    var newComments = comments.concat([comment]);
-    this.setState({data: newComments});
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        this.setState({data: comments});
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>댓글</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

축하합니다! #

-

몇 단계를 거쳐 간단하게 댓글창을 만들어 보았습니다. 왜 React인가에서 더 알아보거나, 혹은 API 레퍼런스에 뛰어들어 해킹을 시작하세요! 행운을 빕니다!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tutorial-zh-CN.html b/docs/tutorial-zh-CN.html deleted file mode 100644 index 73bc013686..0000000000 --- a/docs/tutorial-zh-CN.html +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - - 教程 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 教程 -

-
- -

我们将建立一个你可以放进博客的简单却真实的评论框,一个 Disqus、LiveFyre 或 Facebook comments 提供的实时评论的基础版本。

- -

我们将提供:

- -
    -
  • 一个所有评论的视图
  • -
  • 一个用于提交评论的表单
  • -
  • 为你提供制定后台的挂钩(Hooks)
  • -
- -

同时也会有一些简洁的功能:

- -
    -
  • 优化的评论: 评论在它们保存到服务器之前就显示在列表里,所以感觉很快。
  • -
  • 实时更新: 其他用户的评论被实时浮现到评论中。
  • -
  • Markdown格式化: 用户可以用Markdown格式化它们的文字。
  • -
-

想要跳过所有内容,只查看源代码? #

-

全在 GitHub .

-

运行服务器 #

-

为了开始本教程,我们将要需要一个运行着的服务器。这将是我们纯粹用来获取和保存数据的伺服终端。为了让这尽可能的容易,我们已经用许多不同的语言编写了简单的服务器,它正好完成我们需要的事。 你可以查看源代码 或者 下载 zip 文件 包括了所有你开始学习需要的东西

- -

为了简单起见,我们将要运行的服务器使用 JSON 文件作为数据库。你不会在生产环境运行这个,但是它让我们更容易模拟使用一个API时你可能会做的事。一旦你启动服务器,它将会支持我们的API终端,同时也将伺服我们需要的静态页面。

-

开始 #

-

对于此教程,我们将使它尽可能的容易。被包括在上面讨论的服务器包里的是一个我们将在其中工作的 HTML 文件。在你最喜欢的编辑器里打开 public/index.html。它应该看起来像这样 (可能有一些小的不同,稍后我们将添加一个额外的 <script> 标签):

-
<!-- index.html -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8" />
-    <title>React Tutorial</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
-    <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-    <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-  </head>
-  <body>
-    <div id="content"></div>
-    <script type="text/babel" src="scripts/example.js"></script>
-    <script type="text/babel">
-      // To get started with this tutorial running your own code, simply remove
-      // the script tag loading scripts/example.js and start writing code here.
-    </script>
-  </body>
-</html>
-
-

在本教程剩余的部分,我们将在此 script 标签中编写我们的 JavaScript 代码。我们没有任何高级的实时加载所以在保存以后你需要刷新你的浏览器来观察更新。通过在浏览器打开 http://localhost:3000 关注你的进展。当你没有任何修改第一次加载时,你将看到我们将要准备建立的已经完成的产品。当你准备开始工作,请删除前面的 <script> 标签然后你就可以继续了。

- -
-

注意:

- -

我们在这里引入 jQuery 是因为我们想简化我们未来的 ajax 请求,但这对React的正常工作 不是 必要的。

-
-

你的第一个组件 #

-

React 中都是关于模块化、可组装的组件。以我们的评论框为例,我们将有如下的组件结构:

-
- CommentBox
-  - CommentList
-    - Comment
-  - CommentForm
-
-

让我们构造 CommentBox 组件,仅是一个简单的 <div>

-
// tutorial1.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        Hello, world! I am a CommentBox.
-      </div>
-    );
-  }
-});
-ReactDOM.render(
-  <CommentBox />,
-  document.getElementById('content')
-);
-
-

注意原生的HTML元素以小写开头,而制定的 React 类以大写开头。

-

JSX 语法 #

-

首先你会注意到你的 JavaScript 中 XML 式的语法。我们有一个简单的预编译器,将语法糖转换成这种纯的JavaScript:

-
// tutorial1-raw.js
-var CommentBox = React.createClass({displayName: 'CommentBox',
-  render: function() {
-    return (
-      React.createElement('div', {className: "commentBox"},
-        "Hello, world! I am a CommentBox."
-      )
-    );
-  }
-});
-ReactDOM.render(
-  React.createElement(CommentBox, null),
-  document.getElementById('content')
-);
-
-

它的使用是可选的,但是我们发现 JSX 语法比单纯的 JavaScript 更加容易使用。阅读更多关于JSX 语法的文章

-

What's going on #

-

我们在一个 JavaScript 对象中传递一些方法到 React.createClass() 来创建一个新的React组件。这些方法中最重要的是 render,该方法返回一颗 React 组件树,这棵树最终将会渲染成 HTML。

- -

这个 <div> 标签不是真实的DOM节点;他们是 React div 组件的实例化。你可以把这些看做是React知道如何处理的标记或者是一些数据 。React 是安全的。我们不生成 HTML 字符串,因此XSS防护是默认特性。

- -

你没有必要返回基本的 HTML。你可以返回一个你(或者其他人)创建的组件树。这就使 React 组件化:一个可维护前端的关键原则。

- -

ReactDOM.render() 实例化根组件,启动框架,注入标记到原始的 DOM 元素中,作为第二个参数提供。

- -

ReactDOM 模块暴露了 DOM 相关的方法, 而 React 保有被不同平台的 React 共享的核心工具 (例如 React Native)。

- -

对于本教程 ReactDOM.render 保持在脚本底部是很重要的。ReactDOM.render 应该只在复合组件被定义之后被调用。

-

组合组件 #

-

让我们为 CommentListCommentForm 建造骨架,它们将会,再一次的,是一些简单的 <div>。添加这两个组件到你的文件里,保持现存的 CommentBox 声明和 ReactDOM.render 调用:

-
// tutorial2.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        Hello, world! I am a CommentList.
-      </div>
-    );
-  }
-});
-
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <div className="commentForm">
-        Hello, world! I am a CommentForm.
-      </div>
-    );
-  }
-});
-
-

接着,更新 CommentBox 以使用这些新的组件:

-
// tutorial3.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

注意我们是如何混合 HTML 标签和我们建立的组件。HTML 组件是正常的 React 组件,就和你定义的一样,只有一个区别。JSX 编译器会自动重写 HTML 标签为 React.createElement(tagName) 表达式,其它什么都不做。这是为了避免污染全局命名空间。

-

使用 props #

-

让我们创建 Comment 组件,它将依赖于从父级传来的数据。从父级传来的数据在子组件里作为 '属性' 可供使用。 这些 '属性' 可以通过 this.props 访问。使用属性,我们将能读取从 CommentList 传递给 Comment 的数据,并且渲染一些标记:

-
// tutorial4.js
-var Comment = React.createClass({
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {this.props.children}
-      </div>
-    );
-  }
-});
-
-

在 JSX 中,通过将 JavaScript 表达式放在大括号中(作为属性或者子节点),你可以把文本或者 React 组件放置到树中。我们以 this.props 的 keys 访问传递给组件的命名属性,以 this.props.children 访问任何嵌套的元素。

-

组件的属性 #

-

既然我们已经定义了 Comment 组件,我们将要传递作者名和评论文字给它。这允许我们为每个评论重用相同的代码。现在让我们在我们的 CommentList 里添加一些评论。

-
// tutorial5.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        <Comment author="Pete Hunt">This is one comment</Comment>
-        <Comment author="Jordan Walke">This is *another* comment</Comment>
-      </div>
-    );
-  }
-});
-
-

注意,我们已经从 CommentList 组件传递了一些数据到 Comment 组件。例如,我们传递了 Pete Hunt (通过属性)和 This is one comment (通过 XML-风格的子节点)给第一个 Comment。如上面提到的那样, Comment 组件将会通过 this.props.authorthis.props.children 访问 这些 '属性'。

-

添加 Markdown #

-

Markdown 是一种简单的内联格式化你的文字的方法。例如,用星号包围文本将会使其强调突出。

- -

在本教程中我们使用第三方库 remarkable,它接受 Markdown 文本并且转换为原始的 HTML。我们已经在初始的页面标记里包含了这个库,所以我们可以直接开始使用它,让我们转换评论文本为 Markdown 并输出它:

-
// tutorial6.js
-var Comment = React.createClass({
-  render: function() {
-    var md = new Remarkable();
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {md.render(this.props.children.toString())}
-      </div>
-    );
-  }
-});
-
-

我们在这里唯一做的就是调用 remarkable 库。我们需要把 从 React 的包裹文本来的 this.props.children 转换成 remarkable 能理解的原始字符串,所以我们显示地调用了toString()

- -

但是这里有一个问题!我们渲染的评论在浏览器里看起来像这样: "<p>This is <em>another</em> comment</p>" 。我们想让这些标签真正地渲染为 HTML。

- -

那是 React 在保护你免受 XSS 攻击。有一个方法解决这个问题,但是框架会警告你别使用这种方法:

-
// tutorial7.js
-var Comment = React.createClass({
-  rawMarkup: function() {
-    var md = new Remarkable();
-    var rawMarkup = md.render(this.props.children.toString());
-    return { __html: rawMarkup };
-  },
-
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        <span dangerouslySetInnerHTML={this.rawMarkup()} />
-      </div>
-    );
-  }
-});
-
-

这是一个特殊的 API,故意让插入原始的 HTML 变得困难,但是对于 remarkable 我们将利用这个后门。

- -

记住: 使用这个功能你会依赖于 remarkable 是安全的。

-

挂钩数据模型 #

-

到目前为止我们已经完成了在源码里直接插入评论。作为替代,让我们渲染一团 JSON 数据到评论列表里。最终数据将会来自服务器,但是现在,写在你的源代码中:

-
// tutorial8.js
-var data = [
-  {id: 1, author: "Pete Hunt", text: "This is one comment"},
-  {id: 2, author: "Jordan Walke", text: "This is *another* comment"}
-];
-
-

我们需要以一种模块化的方式将这个数据传入到 CommentList。修改 CommentBoxReactDOM.render() 方法,以便于通过 props 传入数据到 CommentList

-
// tutorial9.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.props.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox data={data} />,
-  document.getElementById('content')
-);
-
-

既然现在数据在 CommentList 中可用了,让我们动态地渲染评论:

-
// tutorial10.js
-var CommentList = React.createClass({
-  render: function() {
-    var commentNodes = this.props.data.map(function(comment) {
-      return (
-        <Comment author={comment.author} key={comment.id}>
-          {comment.text}
-        </Comment>
-      );
-    });
-    return (
-      <div className="commentList">
-        {commentNodes}
-      </div>
-    );
-  }
-});
-
-

就是这样!

-

从服务器获取数据 #

-

让我们用一些来自服务器的动态数据替换硬编码的数据。我们将移除数据的prop,用获取数据的URL来替换它:

-
// tutorial11.js
-ReactDOM.render(
-  <CommentBox url="/api/comments" />,
-  document.getElementById('content')
-);
-
-

这个组件不同于和前面的组件,因为它必须重新渲染自己。该组件将不会有任何数据,直到请求从服务器返回,此时该组件或许需要渲染一些新的评论。

- -

注意: 此代码在这个阶段不会工作。

-

Reactive state #

-

迄今为止,基于它自己的props,每个组件都渲染了自己一次。props 是不可变的:它们从父级传来并被父级“拥有”。为了实现交互,我们给组件引进了可变的 statethis.state 是组件私有的,可以通过调用 this.setState() 改变它。每当state更新,组件就重新渲染自己。

- -

render() 方法被声明为一个带有 this.propsthis.state 的函数。框架保证了 UI 总是与输入一致。

- -

当服务器获取数据时,我们将会改变我们已有的评论数据。让我们给 CommentBox 组件添加一组评论数据作为它的状态:

-
// tutorial12.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

getInitialState() 在生命周期里只执行一次,并设置组件的初始状态。

-

更新状态 #

-

当组件第一次创建时,我们想从服务器获取一些 JSON 并且更新状态以反映最新的数据。我们将用 jQuery 来发送一个异步请求到我们刚才启动的服务器以获取我们需要的数据。这些数据已经被包含在了你已启动的服务器里(基于comments.json文件),所以一旦被获取,this.state.data 会看起来像这样:

-
[
-  {"author": "Pete Hunt", "text": "This is one comment"},
-  {"author": "Jordan Walke", "text": "This is *another* comment"}
-]
-
// tutorial13.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

这里, componentDidMount 是一个当组件被渲染时被React自动调用的方法。动态更新的关键是对 this.setState() 的调用。我们用新的从服务器来的替换掉旧的评论组,然后UI自动更新自己。因为这种反应性,仅是一个微小的变化就添加了实时更新。我们这里将用简单的轮询,但是你可以容易的使用 WebSockets 或者其他技术。

-
// tutorial14.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox url="/api/comments" pollInterval={2000} />,
-  document.getElementById('content')
-);
-
-

我们在这里做的全部事情是把 AJAX 调用移动到独立的方法里,然后在组件第一次加载时及其后每2秒 调用它。试着在你的浏览器里运行它并且改变 comments.json 文件(在你的服务器的相同目录);2秒内,变化将会显现!

-

添加新评论 #

-

现在是时候建立表单了,我们的 CommentForm 组件应该询问用户他们的名字和评论文本然后发送一个请求到服务器来保存评论.

-
// tutorial15.js
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input type="text" placeholder="Your name" />
-        <input type="text" placeholder="Say something..." />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-

受控组件 #

-

对于传统的 DOM, input 元素被渲染并且浏览器管理它的状态(它的渲染值)。结果是,DOM的实际值会和组件不同。这是不理想的,因为视图的值会和组件的值不同。在React中,组件应该总是表示视图的值而不只是在初始化时。

- -

因此,我们将使用 this.state 来在用户输入时保存输入。我们定义一个初始 state,它带有 authortext 两个属性并将他们设置为空字符串。在我们的 <input> 元素里,我们设置 value prop 来反映组件的 state 并给他们附加 onChange 事件处理。这些带有设置了 value<input> 元素被称为受控组件。更多关于受控组件请阅读 Forms article

-
// tutorial16.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-
事件 #
-

React使用小驼峰命名规范(camelCase)给组件绑定事件处理器。我们附加 onChange 给两个 <input> 元素。现在,当用户输入文本到 <input> 中,被附加的 onChange 回调函数被激发并且组件的 state 被修改。然后,被渲染的 input 元素的值将会更新以反映当前组件的 state

-

提交表单 #

-

让我们使表单具有交互性。当用户提交表单时,我们应该清除它,提交一个请求到服务器,并刷新评论列表。让我们监听表单的提交事件并清除它。

-
// tutorial17.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.state.author.trim();
-    var text = this.state.text.trim();
-    if (!text || !author) {
-      return;
-    }
-    // TODO: send request to the server
-    this.setState({author: '', text: ''});
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-
-

我们给表单绑定一个onSubmit处理器,它在表单提交了合法的输入后清空表单字段。

- -

在事件中调用preventDefault()来阻止浏览器提交表单的默认行为。

-
回调函数作为属性 #
-

当用户提交评论时,我们需要刷新评论列表来包含这条新评论。在CommentBox中完成所有逻辑是有道理的,因为CommentBox 拥有代表了评论列表的状态(state)。

- -

我们需要从子组件传回数据到它的父组件。我们在父组件的render方法中以传递一个新的回调函数(handleCommentSubmit)到子组件完成这件事,绑定它到子组件的 onCommentSubmit 事件上。无论事件什么时候触发,回调函数都将被调用:

-
// tutorial18.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    // TODO: submit to the server and refresh the list
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-
-

既然 CommentBox 已经通过 onCommentSubmit prop 使回调函数对于 CommentForm 可用,CommentForm 就可以在用户提交表单时调用回调函数:

-
// tutorial19.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.state.author.trim();
-    var text = this.state.text.trim();
-    if (!text || !author) {
-      return;
-    }
-    this.props.onCommentSubmit({author: author, text: text});
-    this.setState({author: '', text: ''});
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-
-

既然现在回调函数已经就绪,我们所需要做的就是提交到服务器然后刷新列表:

-
// tutorial20.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

优化: 优化的更新 #

-

我们的应用现在已经功能完备,但是它感觉很慢,因为在评论出现在列表前必须等待请求完成。我们可以优化添加这条评论到列表以使应用感觉更快。

-
// tutorial21.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    var comments = this.state.data;
-    // Optimistically set an id on the new comment. It will be replaced by an
-    // id generated by the server. In a production application you would likely
-    // not use Date.now() for this and would have a more robust system in place.
-    comment.id = Date.now();
-    var newComments = comments.concat([comment]);
-    this.setState({data: newComments});
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        this.setState({data: comments});
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

祝贺! #

-

你刚刚通过几个简单的步骤建立了一个评论框。学习更多关于为什么使用 React, 或者深入 API 参考 开始钻研!祝你好运!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/tutorial.html b/docs/tutorial.html deleted file mode 100644 index 53fce75f3b..0000000000 --- a/docs/tutorial.html +++ /dev/null @@ -1,1167 +0,0 @@ - - - - - - - Tutorial | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Tutorial -

-
- -

We'll be building a simple but realistic comments box that you can drop into a blog, a basic version of the realtime comments offered by Disqus, LiveFyre or Facebook comments.

- -

We'll provide:

- -
    -
  • A view of all of the comments
  • -
  • A form to submit a comment
  • -
  • Hooks for you to provide a custom backend
  • -
- -

It'll also have a few neat features:

- -
    -
  • Optimistic commenting: comments appear in the list before they're saved on the server so it feels fast.
  • -
  • Live updates: other users' comments are popped into the comment view in real time.
  • -
  • Markdown formatting: users can use Markdown to format their text.
  • -
-

Want to skip all this and just see the source? #

-

It's all on GitHub.

-

Running a server #

-

In order to start this tutorial, we're going to require a running server. This will serve purely as an API endpoint which we'll use for getting and saving data. In order to make this as easy as possible, we've created a simple server in a number of scripting languages that does exactly what we need it to do. You can view the source or download a zip file containing everything needed to get started.

- -

For sake of simplicity, the server we will run uses a JSON file as a database. You would not run this in production but it makes it easy to simulate what you might do when consuming an API. Once you start the server, it will support our API endpoint and it will also serve the static pages we need.

-

Getting started #

-

For this tutorial, we're going to make it as easy as possible. Included in the server package discussed above is an HTML file which we'll work in. Open up public/index.html in your favorite editor. It should look something like this:

-
<!-- index.html -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8" />
-    <title>React Tutorial</title>
-    <script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-    <script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
-    <script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
-    <script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
-  </head>
-  <body>
-    <div id="content"></div>
-    <script type="text/babel" src="scripts/example.js"></script>
-    <script type="text/babel">
-      // To get started with this tutorial running your own code, simply remove
-      // the script tag loading scripts/example.js and start writing code here.
-    </script>
-  </body>
-</html>
-
-

For the remainder of this tutorial, we'll be writing our JavaScript code in this script tag. We don't have any advanced live-reloading so you'll need to refresh your browser to see updates after saving. Follow your progress by opening http://localhost:3000 in your browser (after starting the server). When you load this for the first time without any changes, you'll see the finished product of what we're going to build. When you're ready to start working, just delete the preceding <script> tag and then you can continue.

- -
-

Note:

- -

We included jQuery here because we want to simplify the code of our future AJAX calls, but it's NOT mandatory for React to work.

-
-

Your first component #

-

React is all about modular, composable components. For our comment box example, we'll have the following component structure:

-
- CommentBox
-  - CommentList
-    - Comment
-  - CommentForm
-
-

Let's build the CommentBox component, which is just a simple <div>:

-
// tutorial1.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        Hello, world! I am a CommentBox.
-      </div>
-    );
-  }
-});
-ReactDOM.render(
-  <CommentBox />,
-  document.getElementById('content')
-);
-
-

Note that native HTML element names start with a lowercase letter, while custom React class names begin with an uppercase letter.

-

JSX Syntax #

-

The first thing you'll notice is the XML-ish syntax in your JavaScript. We have a simple precompiler that translates the syntactic sugar to this plain JavaScript:

-
// tutorial1-raw.js
-var CommentBox = React.createClass({displayName: 'CommentBox',
-  render: function() {
-    return (
-      React.createElement('div', {className: "commentBox"},
-        "Hello, world! I am a CommentBox."
-      )
-    );
-  }
-});
-ReactDOM.render(
-  React.createElement(CommentBox, null),
-  document.getElementById('content')
-);
-
-

Its use is optional but we've found JSX syntax easier to use than plain JavaScript. Read more on the JSX Syntax article.

-

What's going on #

-

We pass some methods in a JavaScript object to React.createClass() to create a new React component. The most important of these methods is called render which returns a tree of React components that will eventually render to HTML.

- -

The <div> tags are not actual DOM nodes; they are instantiations of React div components. You can think of these as markers or pieces of data that React knows how to handle. React is safe. We are not generating HTML strings so XSS protection is the default.

- -

You do not have to return basic HTML. You can return a tree of components that you (or someone else) built. This is what makes React composable: a key tenet of maintainable frontends.

- -

ReactDOM.render() instantiates the root component, starts the framework, and injects the markup into a raw DOM element, provided as the second argument.

- -

The ReactDOM module exposes DOM-specific methods, while React has the core tools shared by React on different platforms (e.g., React Native).

- -

It is important that ReactDOM.render remain at the bottom of the script for this tutorial. ReactDOM.render should only be called after the composite components have been defined.

-

Composing components #

-

Let's build skeletons for CommentList and CommentForm which will, again, be simple <div>s. Add these two components to your file, keeping the existing CommentBox declaration and ReactDOM.render call:

-
// tutorial2.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        Hello, world! I am a CommentList.
-      </div>
-    );
-  }
-});
-
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <div className="commentForm">
-        Hello, world! I am a CommentForm.
-      </div>
-    );
-  }
-});
-
-

Next, update the CommentBox component to use these new components:

-
// tutorial3.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

Notice how we're mixing HTML tags and components we've built. HTML components are regular React components, just like the ones you define, with one difference. The JSX compiler will automatically rewrite HTML tags to React.createElement(tagName) expressions and leave everything else alone. This is to prevent the pollution of the global namespace.

-

Using props #

-

Let's create the Comment component, which will depend on data passed in from our CommentList component. Data passed in from the CommentList component is available as a 'property' on our Comment component. These 'properties' are accessed through this.props. Using props, we will be able to read the data passed to the Comment from the CommentList, and render some markup:

-
// tutorial4.js
-var Comment = React.createClass({
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {this.props.children}
-      </div>
-    );
-  }
-});
-
-

By surrounding a JavaScript expression in braces inside JSX (as either an attribute or child), you can drop text or React components into the tree. We access named attributes passed to the component as keys on this.props and any nested elements as this.props.children.

-

Component Properties #

-

Now that we have defined the Comment component, we will want to pass it the author name and comment text. This allows us to reuse the same code for each unique comment. Now let's add some comments within our CommentList:

-
// tutorial5.js
-var CommentList = React.createClass({
-  render: function() {
-    return (
-      <div className="commentList">
-        <Comment author="Pete Hunt">This is one comment</Comment>
-        <Comment author="Jordan Walke">This is *another* comment</Comment>
-      </div>
-    );
-  }
-});
-
-

Note that we have passed some data from the parent CommentList component to the child Comment components. For example, we passed Pete Hunt (via the author attribute) and This is one comment (via an XML-like child node) to the first Comment. As noted above, the Comment component will access these 'properties' through this.props.author, and this.props.children.

-

Adding Markdown #

-

Markdown is a simple way to format your text inline. For example, surrounding text with asterisks will make it emphasized.

- -

In this tutorial we use a third-party library remarkable which takes Markdown text and converts it to raw HTML. We already included this library with the original markup for the page, so we can just start using it. Let's convert the comment text to Markdown and output it:

-
// tutorial6.js
-var Comment = React.createClass({
-  render: function() {
-    var md = new Remarkable();
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        {md.render(this.props.children.toString())}
-      </div>
-    );
-  }
-});
-
-

All we're doing here is calling the remarkable library. We need to convert this.props.children from React's wrapped text to a raw string that remarkable will understand so we explicitly call toString().

- -

But there's a problem! Our rendered comments look like this in the browser: "<p>This is <em>another</em> comment</p>". We want those tags to actually render as HTML.

- -

That's React protecting you from an XSS attack. There's a way to get around it but the framework warns you not to use it:

-
// tutorial7.js
-var Comment = React.createClass({
-  rawMarkup: function() {
-    var md = new Remarkable();
-    var rawMarkup = md.render(this.props.children.toString());
-    return { __html: rawMarkup };
-  },
-
-  render: function() {
-    return (
-      <div className="comment">
-        <h2 className="commentAuthor">
-          {this.props.author}
-        </h2>
-        <span dangerouslySetInnerHTML={this.rawMarkup()} />
-      </div>
-    );
-  }
-});
-
-

This is a special API that intentionally makes it difficult to insert raw HTML, but for remarkable we'll take advantage of this backdoor.

- -

Remember: by using this feature you're relying on remarkable to be secure. In this case, remarkable automatically strips HTML markup and insecure links from the output.

-

Hook up the data model #

-

So far we've been inserting the comments directly in the source code. Instead, let's render a blob of JSON data into the comment list. Eventually this will come from the server, but for now, write it in your source:

-
// tutorial8.js
-var data = [
-  {id: 1, author: "Pete Hunt", text: "This is one comment"},
-  {id: 2, author: "Jordan Walke", text: "This is *another* comment"}
-];
-
-

We need to get this data into CommentList in a modular way. Modify CommentBox and the ReactDOM.render() call to pass this data into the CommentList via props:

-
// tutorial9.js
-var CommentBox = React.createClass({
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.props.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox data={data} />,
-  document.getElementById('content')
-);
-
-

Now that the data is available in the CommentList, let's render the comments dynamically:

-
// tutorial10.js
-var CommentList = React.createClass({
-  render: function() {
-    var commentNodes = this.props.data.map(function(comment) {
-      return (
-        <Comment author={comment.author} key={comment.id}>
-          {comment.text}
-        </Comment>
-      );
-    });
-    return (
-      <div className="commentList">
-        {commentNodes}
-      </div>
-    );
-  }
-});
-
-

That's it!

-

Fetching from the server #

-

Let's replace the hard-coded data with some dynamic data from the server. We will remove the data prop and replace it with a URL to fetch:

-
// tutorial11.js
-ReactDOM.render(
-  <CommentBox url="/api/comments" />,
-  document.getElementById('content')
-);
-
-

This component is different from the prior components because it will have to re-render itself. The component won't have any data until the request from the server comes back, at which point the component may need to render some new comments.

- -

Note: the code will not be working at this step.

-

Reactive state #

-

So far, based on its props, each component has rendered itself once. props are immutable: they are passed from the parent and are "owned" by the parent. To implement interactions, we introduce mutable state to the component. this.state is private to the component and can be changed by calling this.setState(). When the state updates, the component re-renders itself.

- -

render() methods are written declaratively as functions of this.props and this.state. The framework guarantees the UI is always consistent with the inputs.

- -

When the server fetches data, we will be changing the comment data we have. Let's add an array of comment data to the CommentBox component as its state:

-
// tutorial12.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

getInitialState() executes exactly once during the lifecycle of the component and sets up the initial state of the component.

-

Updating state #

-

When the component is first created, we want to GET some JSON from the server and update the state to reflect the latest data. We're going to use jQuery to make an asynchronous request to the server we started earlier to fetch the data we need. The data is already included in the server you started (based on the comments.json file), so once it's fetched, this.state.data will look something like this:

-
[
-  {"id": "1", "author": "Pete Hunt", "text": "This is one comment"},
-  {"id": "2", "author": "Jordan Walke", "text": "This is *another* comment"}
-]
-
// tutorial13.js
-var CommentBox = React.createClass({
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-

Here, componentDidMount is a method called automatically by React after a component is rendered for the first time. The key to dynamic updates is the call to this.setState(). We replace the old array of comments with the new one from the server and the UI automatically updates itself. Because of this reactivity, it is only a minor change to add live updates. We will use simple polling here but you could easily use WebSockets or other technologies.

-
// tutorial14.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <CommentBox url="/api/comments" pollInterval={2000} />,
-  document.getElementById('content')
-);
-
-

All we have done here is move the AJAX call to a separate method and call it when the component is first loaded and every 2 seconds after that. Try running this in your browser and changing the comments.json file (in the same directory as your server); within 2 seconds, the changes will show!

-

Adding new comments #

-

Now it's time to build the form. Our CommentForm component should ask the user for their name and comment text and send a request to the server to save the comment.

-
// tutorial15.js
-var CommentForm = React.createClass({
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input type="text" placeholder="Your name" />
-        <input type="text" placeholder="Say something..." />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-

Controlled components #

-

With the traditional DOM, input elements are rendered and the browser manages the state (its rendered value). As a result, the state of the actual DOM will differ from that of the component. This is not ideal as the state of the view will differ from that of the component. In React, components should always represent the state of the view and not only at the point of initialization.

- -

Hence, we will be using this.state to save the user's input as it is entered. We define an initial state with two properties author and text and set them to be empty strings. In our <input> elements, we set the value prop to reflect the state of the component and attach onChange handlers to them. These <input> elements with a value set are called controlled components. Read more about controlled components on the Forms article.

-
// tutorial16.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  render: function() {
-    return (
-      <form className="commentForm">
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-

Events #

-

React attaches event handlers to components using a camelCase naming convention. We attach onChange handlers to the two <input> elements. Now, as the user enters text into the <input> fields, the attached onChange callbacks are fired and the state of the component is modified. Subsequently, the rendered value of the input element will be updated to reflect the current component state.

- -

(The astute reader may be surprised that these event handlers work as described, given that the method references are not explicitly bound to this. React.createClass(...) automatically binds each method to its component instance, obviating the need for explicit binding.)

-

Submitting the form #

-

Let's make the form interactive. When the user submits the form, we should clear it, submit a request to the server, and refresh the list of comments. To start, let's listen for the form's submit event and clear it.

-
// tutorial17.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.state.author.trim();
-    var text = this.state.text.trim();
-    if (!text || !author) {
-      return;
-    }
-    // TODO: send request to the server
-    this.setState({author: '', text: ''});
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-
-

We attach an onSubmit handler to the form that clears the form fields when the form is submitted with valid input.

- -

Call preventDefault() on the event to prevent the browser's default action of submitting the form.

-

Callbacks as props #

-

When a user submits a comment, we will need to refresh the list of comments to include the new one. It makes sense to do all of this logic in CommentBox since CommentBox owns the state that represents the list of comments.

- -

We need to pass data from the child component back up to its parent. We do this in our parent's render method by passing a new callback (handleCommentSubmit) into the child, binding it to the child's onCommentSubmit event. Whenever the event is triggered, the callback will be invoked:

-
// tutorial18.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    // TODO: submit to the server and refresh the list
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-
-

Now that CommentBox has made the callback available to CommentForm via the onCommentSubmit prop, the CommentForm can call the callback when the user submits the form:

-
// tutorial19.js
-var CommentForm = React.createClass({
-  getInitialState: function() {
-    return {author: '', text: ''};
-  },
-  handleAuthorChange: function(e) {
-    this.setState({author: e.target.value});
-  },
-  handleTextChange: function(e) {
-    this.setState({text: e.target.value});
-  },
-  handleSubmit: function(e) {
-    e.preventDefault();
-    var author = this.state.author.trim();
-    var text = this.state.text.trim();
-    if (!text || !author) {
-      return;
-    }
-    this.props.onCommentSubmit({author: author, text: text});
-    this.setState({author: '', text: ''});
-  },
-  render: function() {
-    return (
-      <form className="commentForm" onSubmit={this.handleSubmit}>
-        <input
-          type="text"
-          placeholder="Your name"
-          value={this.state.author}
-          onChange={this.handleAuthorChange}
-        />
-        <input
-          type="text"
-          placeholder="Say something..."
-          value={this.state.text}
-          onChange={this.handleTextChange}
-        />
-        <input type="submit" value="Post" />
-      </form>
-    );
-  }
-});
-
-

Now that the callbacks are in place, all we have to do is submit to the server and refresh the list:

-
// tutorial20.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

Optimization: optimistic updates #

-

Our application is now feature complete but it feels slow to have to wait for the request to complete before your comment appears in the list. We can optimistically add this comment to the list to make the app feel faster.

-
// tutorial21.js
-var CommentBox = React.createClass({
-  loadCommentsFromServer: function() {
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      cache: false,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  handleCommentSubmit: function(comment) {
-    var comments = this.state.data;
-    // Optimistically set an id on the new comment. It will be replaced by an
-    // id generated by the server. In a production application you would likely
-    // not use Date.now() for this and would have a more robust system in place.
-    comment.id = Date.now();
-    var newComments = comments.concat([comment]);
-    this.setState({data: newComments});
-    $.ajax({
-      url: this.props.url,
-      dataType: 'json',
-      type: 'POST',
-      data: comment,
-      success: function(data) {
-        this.setState({data: data});
-      }.bind(this),
-      error: function(xhr, status, err) {
-        this.setState({data: comments});
-        console.error(this.props.url, status, err.toString());
-      }.bind(this)
-    });
-  },
-  getInitialState: function() {
-    return {data: []};
-  },
-  componentDidMount: function() {
-    this.loadCommentsFromServer();
-    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
-  },
-  render: function() {
-    return (
-      <div className="commentBox">
-        <h1>Comments</h1>
-        <CommentList data={this.state.data} />
-        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
-      </div>
-    );
-  }
-});
-

Congrats! #

-

You have just built a comment box in a few simple steps. Learn more about why to use React, or dive into the API reference and start hacking! Good luck!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/two-way-binding-helpers-it-IT.html b/docs/two-way-binding-helpers-it-IT.html deleted file mode 100644 index 8e32a1a1f9..0000000000 --- a/docs/two-way-binding-helpers-it-IT.html +++ /dev/null @@ -1,587 +0,0 @@ - - - - - - - Helper Per Binding Bidirezionali | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Helper Per Binding Bidirezionali -

-
- -

ReactLink è una maniera semplice di esprimere binding bidirezionali con React.

- -
-

Nota:

- -

Se hai poca esperienza del framework, nota che ReactLink non è necessario per molte applicazioni e dovrebbe essere utilizzato con cautela.

-
- -

In React, i dati fluiscono in una direzione: dal proprietario ai figli. Questo poiché i dati fluiscono in una sola direzione nel modello di computazione di Von Neumann. Puoi pensare ad esso come "binding unidirezionale dei dati."

- -

Tuttavia, esistono parecchie applicazioni che richiedono di leggere dati e farli fluire nuovamente nel tuo programma. Ad esempio, quando sviluppi dei moduli, vorrai spesso aggiornare uno state di React quando ricevi un input dall'utente. O forse vuoi effettuare il layout in JavaScript e reagire ai cambiamenti nelle dimensioni di alcuni elementi DOM.

- -

In React, questo verrebbe implementato ascoltando un evento "change", leggendo la tua fonte di dati (solitamente il DOM) e chiamando setState() su uno dei tuoi componenti. "Chiudere il ciclo del flusso dei dati" esplicitamente conduce a programmi più comprensibili e mantenibili. Consulta la nostra documentazione sui moduli per maggiori informazioni.

- -

Il binding bidirezionale -- assicurarsi implicitamente che alcuni valori nel DOM siano sempre consistenti con degli state in React -- è più conciso e supporta un'ampia varietà di applicazioni. Abbiamo fornito ReactLink: zucchero sintattico per impostare il pattern del ciclo del flusso di dati descritto in predecenza, ovvero "collegare" una fonte di dati con lo state di React.

- -
-

Nota:

- -

ReactLink è soltanto uno strato di astrazione e convenzioni attorno al pattern onChange/setState(). Non cambia fondamentalmente la maniera in cui i dati fluiscono all'interno della tua applicazione React.

-
-

ReactLink: Prima e Dopo #

-

Ecco un semplice esempio di modulo che non utilizza ReactLink:

-
var NoLink = React.createClass({
-  getInitialState: function() {
-    return {message: 'Ciao!'};
-  },
-  handleChange: function(event) {
-    this.setState({message: event.target.value});
-  },
-  render: function() {
-    var message = this.state.message;
-    return <input type="text" value={message} onChange={this.handleChange} />;
-  }
-});
-
-

Ciò funziona molto bene e il flusso di dati è molto chiaro. Tuttavia, in presenza di un gran numero di campi del modulo può risultare assai prolisso. Utilizziamo ReactLink per risparmiarci la scrittura di un po' di codice:

-
var WithLink = React.createClass({
-  mixins: [React.addons.LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Ciao!'};
-  },
-  render: function() {
-    return <input type="text" valueLink={this.linkState('message')} />;
-  }
-});
-
-

LinkedStateMixin aggiunge un metodo chiamato linkState() al tuo componente React. linkState() restituisce un oggetto ReactLink contenente il valore attuae dello stato React e una callback per cambiarlo.

- -

Gli oggetti ReactLink possono essere passati su e giù nell'albero come proprietà, quindi è facile (ed esplicito) impostare un binding bidirezionale tra un componente in profondità nella gerarchia e dello stato che si trova più in alto nella gerarchia.

- -

Nota che i checkbox hanno un comportamento speciale riguardo il loro attributo value, che è il valore che sarà inviato all'inoltro del modulo se il checkbox è spuntato (il valore predefinito è on). L'attributo value non è aggiornato quando il checkbox viene spuntato o deselezionato. Per i checkbox occorre usare checkedLink anziché valueLink: - -<input type="checkbox" checkedLink={this.linkState('booleanValue')} /> -

-

Dietro le Quinte #

-

Ci sono due ambiti in ReactLink: il posto in cui crei l'istanza di ReactLink e il posto in cui la utilizzi. Per dimostrare quanto sia semplice usare ReactLink, riscriviamo ciascun ambito separatamente perché sia più esplicito.

-

ReactLink Senza LinkedStateMixin #

var WithoutMixin = React.createClass({
-  getInitialState: function() {
-    return {message: 'Ciao!'};
-  },
-  handleChange: function(newValue) {
-    this.setState({message: newValue});
-  },
-  render: function() {
-    var valueLink = {
-      value: this.state.message,
-      requestChange: this.handleChange
-    };
-    return <input type="text" valueLink={valueLink} />;
-  }
-});
-
-

Come puoi vedere, gli oggetti ReactLink sono semplici oggetti che hanno due proprietà: value e requestChange. LinkedStateMixin è altrettanto semplice: popola semplicemente questi campi con un valore da this.state e una callback che invoca this.setState().

-

ReactLink Senza valueLink #

var WithoutLink = React.createClass({
-  mixins: [React.addons.LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Ciao!'};
-  },
-  render: function() {
-    var valueLink = this.linkState('message');
-    var handleChange = function(e) {
-      valueLink.requestChange(e.target.value);
-    };
-    return <input type="text" value={valueLink.value} onChange={handleChange} />;
-  }
-});
-
-

La proprietà valueLink è anche abbastanza semplice. Gestisce semplicemente l'evento onChange e invoca this.props.valueLink.requestChange(), e inoltre utilizza this.props.valueLink.value anziché this.props.value. Tutto qua!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/two-way-binding-helpers-ja-JP.html b/docs/two-way-binding-helpers-ja-JP.html deleted file mode 100644 index 231ebcb2c9..0000000000 --- a/docs/two-way-binding-helpers-ja-JP.html +++ /dev/null @@ -1,584 +0,0 @@ - - - - - - - 2ウェイバインディングのヘルパ | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 2ウェイバインディングのヘルパ -

-
- -

ReactLink はReactで2ウェイバインディングを表現する簡単な方法です。

- -
-

注意: -もしあなたがフレームワークについてあまりよく知らないのであれば、 ReactLink は多くのアプリケーションには必要なく、慎重に使うべきであることに注意してください。

-
- -

Reactでは所有者から子要素へと、データの流れは一方向です。これはデータがVon Neumannのコンピューティングモデルによって一方向にのみ流れるからです。これを「1ウェイデータバインディング」だと考えることができます。

- -

しかし、データやプログラムに戻る流れを読む必要が有るアプリケーションもたくさんあります。例えば、フォームを作る際に、ユーザのインプットを受け取った時には、Reactの state を更新したいと思うことはよくあるでしょう。または、JavaScriptでレイアウトを形作ったり、DOM要素のサイズの変化に反応したいと思うでしょう。

- -

Reactでは、「変更」のイベントを検知し、データソース(普通はDOMです)を読み、コンポーネントのうちの1つの上で setState() を呼ぶことでこの要求を満たすことができます。「データフローのループを止めること」は理解しやすく、維持しやすいプログラムを明確に導きます。詳細な情報については、フォームのドキュメントをご覧ください。

- -

2ウェイバインディングはDOMの値が常にReactの state と一致していることを暗黙に強制しますが、簡潔で、多くの種類のアプリケーションをサポートします。上で説明されているような共通のデータフローループパターンのセットアップや、データソースをReactの state に「接続する」ための糖衣構文である ReactLink が提供されています。

- -
-

注意: -ReactLink は薄いラッパーであり、 onChange/setState() パターンにおける習慣です。Reactアプリケーションのデータフローの方法を根本から変えるようなものではありません。

-
-

ReactLink: ビフォーアフター #

-

以下が、 ReactLink を使用しない単純なフォームの例です。

-
var NoLink = React.createClass({
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  handleChange: function(event) {
-    this.setState({message: event.target.value});
-  },
-  render: function() {
-    var message = this.state.message;
-    return <input type="text" value={message} onChange={this.handleChange} />;
-  }
-});
-
-

これはとてもよく動き、データがどう流れているかとても明確です。しかし、たくさんのフォームのフィールドがあった場合、少し冗長になります。以下のように、 ReactLink を使うことでタイピング量が少なくて済みます。

-
var WithLink = React.createClass({
-  mixins: [React.addons.LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    return <input type="text" valueLink={this.linkState('message')} />;
-  }
-});
-
-

LinkedStateMixinlinkState() と呼ばれるReactコンポーネントにメソッドを追加します。 -linkState() はReactのステータスの現在の値と、それを変更するコールバックを持った ReactLink オブジェクトを返します。

- -

ReactLink オブジェクトはプロパティとして、木構造の上や下に渡される可能性があります。だから、階層の深い位置にいるコンポーネントと階層の高い位置にいるステータスの間の2ウェイバインディングをセットアップすることは簡単(で、明確)です。

- -

チェックボックスはその value 属性に対しての特別な態度を持っていることに注意してください。それは、チェックボックスがチェックされている(デフォルトで on )場合にフォームのサブミットで送信される値です。 value 属性はチェックボックスがチェックされていても、チェックされていなくても、更新されません。チェックボックスについては、valueLink の代わりに、 checkedLink を使うべきです。以下のように。

-
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
-

フードの下 #

-

ReactLink には2つの側面があります。 ReactLink のインスタンスを作成する場所と、それを使う場所です。 ReactLink がどれだけ単純か証明するために、それぞれの側面を分けて、明確に再度記述してみましょう。

-

LinkedStateMixinを使わないReactLink #

var WithoutMixin = React.createClass({
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  handleChange: function(newValue) {
-    this.setState({message: newValue});
-  },
-  render: function() {
-    var valueLink = {
-      value: this.state.message,
-      requestChange: this.handleChange
-    };
-    return <input type="text" valueLink={valueLink} />;
-  }
-});
-
-

今まで見てきたように ReactLink オブジェクトは valuerequestChange プロパティだけを持ったとても単純なオブジェクトです。そして、 LinkedStateMixin も同様に単純です。それらのフィールドを this.state の値と、 this.setState() を呼ぶコールバックで満たします。

-

valueLinkを使わないReactLink #

var WithoutLink = React.createClass({
-  mixins: [React.addons.LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    var valueLink = this.linkState('message');
-    var handleChange = function(e) {
-      valueLink.requestChange(e.target.value);
-    };
-    return <input type="text" value={valueLink.value} onChange={handleChange} />;
-  }
-});
-
-

valueLink プロパティも同様にとても単純です。単純に onChange イベントをハンドルし、 this.props.valueLink.requestChange() を呼び、 this.props.value の代わりに this.props.valueLink.value を使用します。それだけです!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/two-way-binding-helpers-ko-KR.html b/docs/two-way-binding-helpers-ko-KR.html deleted file mode 100644 index 73f649d2aa..0000000000 --- a/docs/two-way-binding-helpers-ko-KR.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - 양방향 바인딩 핼퍼 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 양방향 바인딩 핼퍼 -

-
- -

ReactLink는 React에서 양방향 바인딩을 표현하는 쉬운 방법입니다.

- -
-

주의:

- -

프레임워크를 새로 접하신다면, 대부분의 애플리케이션에서 ReactLink는 필요없고 신중히 사용하셔야 함을 알려드립니다.

-
- -

React에서 데이터 흐름은 소유주에서 자식으로의 단방향입니다. 이는 폰 노이만 컴퓨팅 모델의 데이터가 단방향으로 흐르기 때문입니다. 이것을 "단방향 데이터 바인딩"으로 생각하셔도 됩니다.

- -

하지만 많은 애플리케이션에서 데이터를 요청해서 프로그램으로 돌려줍니다. 예를 들어, 폼을 개발한다면, 사용자 입력을 받았을 때 state를 바꾸거나, JavaScript안에서 레이아웃을 바꾸고 그에 따라 어떤 DOM 엘리먼트의 크기를 바꾸게 하고 싶을 수도 있습니다.

- -

React에서 이는 "change" 이벤트를 감시하고 데이터 소스(보통 DOM)에서 읽어 컴포넌트에서 setState()를 호출하는 식으로 할 수 있습니다. "데이터 흐름 반복을 제한"하면 더 이해하기 편하고, 쉽게 유지보수할 수 있는 프로그램이 만들어지는 것은 명확합니다. 더 자세한 내용은 폼 문서를 확인하세요.

- -

양방향 바인딩(묵시적으로 DOM의 어떤 값은 React state와 일치하도록 강제하는 것)은 간결하기도 하고 다양한 애플리케이션을 지원 할 수 있습니다. React는 ReactLink를 제공합니다. 이는 위에서 설명한 일반적인 데이터 흐름 반복 패턴을 설정하거나, 어떤 데이터 소스를 React state로 "링크하는" 편의 문법입니다.

- -
-

주의:

- -

ReactLink는 얇은 레퍼고 onChange/setState()패턴 부분의 관례일 뿐입니다. React 애플리케이션에서의 데이터 흐름을 근본적으로 바꾸지는 않습니다.

-
-

ReactLink: 적용 전후 #

-

ReactLink를 사용하지 않는 간단한 폼 예제입니다.

-
var NoLink = React.createClass({
-  getInitialState: function() {
-    return {message: '안녕!'};
-  },
-  handleChange: function(event) {
-    this.setState({message: event.target.value});
-  },
-  render: function() {
-    var message = this.state.message;
-    return <input type="text" value={message} onChange={this.handleChange} />;
-  }
-});
-
-

이것은 정말 잘 동작하고, 데이터가 어떻게 흐르는지 매우 명확하게 보여지지만, 폼필드가 많을 경우 약간 장황해 질 수 있습니다. 타이핑을 줄이기 위해 ReactLink를 사용해 보겠습니다.

-
var LinkedStateMixin = require('react-addons-linked-state-mixin');
-
-var WithLink = React.createClass({
-  mixins: [LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    return <input type="text" valueLink={this.linkState('message')} />;
-  }
-});
-
-

LinkedStateMixin는 React 컴포넌트에 linkState()라는 메서드를 추가합니다. linkState()는 React state의 현재 값과 그것을 변경할 때의 콜백을 가지는 ReactLink 객체를 리턴합니다.

- -

ReactLink 객체는 props로 트리의 위나 아래로 넘길 수 있어서, 쉽고 명확하게 계층구조에서 깊이 있는 컴포넌트와 높이 있는 state 사이의 양방향 바인딩을 설정할 수 있습니다.

- -

checkbox의 value 어트리뷰트는 다른 것과 다르게 checkbox가 체크되었을 때 폼 submit에 값이 전달되는 것에 주의하세요.(기본값 on) 그래서 value 어트리뷰트는 checkbox가 체크되거나 해제될 때 업데이트되지 않습니다. checkbox에서는 valueLink대신 checkedLink를 사용하셔야 합니다. - -<input type="checkbox" checkedLink={this.linkState('booleanValue')} /> -

-

내부 구조 #

-

ReactLink에는 크게 인스턴스를 생성하는 면과 사용하는 면이 있습니다. ReactLink가 얼마나 간단한지 확인하기 위해, 이 부분들을 보다 명시적으로 고쳐 봅시다.

-

LinkedStateMixin 없이 ReactLink 쓰기 #

var WithoutMixin = React.createClass({
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  handleChange: function(newValue) {
-    this.setState({message: newValue});
-  },
-  render: function() {
-    var valueLink = {
-      value: this.state.message,
-      requestChange: this.handleChange
-    };
-    return <input type="text" valueLink={valueLink} />;
-  }
-});
-
-

보시다시피, ReactLink 객체는 valuerequestChange prop만 가지는 매우 간단한 객체입니다. LinkedStateMixin도 간단합니다. 그냥 this.state의 값과 this.setState()에서 호출되는 콜백을 필드로 가질 뿐입니다.

-

valueLink 없이 ReactLink 쓰기 #

var LinkedStateMixin = require('react-addons-linked-state-mixin');
-
-var WithoutLink = React.createClass({
-  mixins: [LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    var valueLink = this.linkState('message');
-    var handleChange = function(e) {
-      valueLink.requestChange(e.target.value);
-    };
-    return <input type="text" value={valueLink.value} onChange={handleChange} />;
-  }
-});
-
-

valueLink prop도 간단합니다. 단순히 onChange 이벤트를 처리하고 this.props.valueLink.requestChange()를 호출하고 this.props.value대신 this.props.valueLink.value를 사용합니다. 그게 다에요!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/two-way-binding-helpers-zh-CN.html b/docs/two-way-binding-helpers-zh-CN.html deleted file mode 100644 index a57a561668..0000000000 --- a/docs/two-way-binding-helpers-zh-CN.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - 双向绑定辅助 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 双向绑定辅助 -

-
- -

ReactLink 是一个用React表达双向绑定的简单方法。

- -
-

注意:

- -

在 React v15 中 ReactLink 被弃用了。推荐明确的设置值和变动的处理,而不是使用 ReactLink。

-
- -

在React里,数据单向流动: 从拥有者到子级。这是因为数据只单向流动the Von Neumann model of computing。你可以把它想象为 “单向数据绑定”。

- -

然而,有很多应用需要你去读某些数据并回流他们到你的程序。例如,当开发forms,你会常常想更新一些React state 当你收到用户输入的时候。或者也许你想在JavaScript完成布局并相应一些DOM元素大小的变化。

- -

在React里,你可以用监听 "change" 事件来实现它,从你的数据源(通常是DOM)读取并在你的某个组件调用 setState() 。明确的"Closing the data flow loop" 致使了更容易理解和维护的程序。更多信息见our forms documentation.

- -

双向绑定 -- 隐含的强迫DOM里的某些值总是和某些React state 同步 -- 简洁并支持大量多样的应用。 我们提供了 ReactLink:设置如上描述的通用数据回流模式的语法糖,或者 "linking" 某些数据结构到 React state.

- -
-

注意:

- -

ReactLink 只是一层对 onChange/setState() 模式的薄包装。它没有根本性的改变你的React应用里数据如何流动。

-
-

ReactLink: 之前和之后 #

-

这里有一个简单的 不用 ReactLink 的 form 例子:

-
var NoLink = React.createClass({
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  handleChange: function(event) {
-    this.setState({message: event.target.value});
-  },
-  render: function() {
-    var message = this.state.message;
-    return <input type="text" value={message} onChange={this.handleChange} />;
-  }
-});
-
-

这个工作的很好并且数据如何流动很清晰,然而,当有大量的 form fields时,可能会有些冗长。让我们使用 ReactLink 来节省我们的输入:

-
var LinkedStateMixin = require('react-addons-linked-state-mixin');
-
-var WithLink = React.createClass({
-  mixins: [LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    return <input type="text" valueLink={this.linkState('message')} />;
-  }
-});
-
-

LinkedStateMixin 添加了一个 linkState() 方法到你的React组件。linkState() 返回一个 ReactLink 包含当前React state值的对象和一个改变它的回调函数。

- -

ReactLink 对象可以作为props在树中上下传递,所以很容易(显示的)在深层次的组件和高层次的state之间 设置双向绑定。

- -

注意 checkboxes 有一个关于他们 value 属性的特殊行为,这个行为是 如果checkbox被选中 值会在表单提交时被发送。 value 不会 checkbox 选中或是不选中时更新。对于checkboxes,你应该用checkedLink 代替 valueLink: - -<input type="checkbox" checkedLink={this.linkState('booleanValue')} /> -

-

引擎盖下 #

-

这里对 ReactLink有两方面:创建ReactLink的实例以及使用它的地方。为了证明ReactLink有多简单,让我们重写两方面一边更好的理解。

-

ReactLink Without LinkedStateMixin #

var WithoutMixin = React.createClass({
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  handleChange: function(newValue) {
-    this.setState({message: newValue});
-  },
-  render: function() {
-    var valueLink = {
-      value: this.state.message,
-      requestChange: this.handleChange
-    };
-    return <input type="text" valueLink={valueLink} />;
-  }
-});
-
-

正如你所见,ReactLink对象是非常简单,只有valuerequestChange属性.并且LinkStateMixin也很简单:它只是作用(populates)于this.state的元素值并且回调名为this.setState()的函数.

-

ReactLink Without valueLink #

var LinkedStateMixin = require('react-addons-linked-state-mixin');
-
-var WithoutLink = React.createClass({
-  mixins: [LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    var valueLink = this.linkState('message');
-    var handleChange = function(e) {
-      valueLink.requestChange(e.target.value);
-    };
-    return <input type="text" value={valueLink.value} onChange={handleChange} />;
-  }
-});
-
-

对于valueLink的属性同样也很简单,它只是简单的处理onChange事件,调用this.props.valueLink.requestChange()的时候也使用this.props.valueLink.requestChange()代替this.props.value.这就是双向绑定!

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/two-way-binding-helpers.html b/docs/two-way-binding-helpers.html index 0cd5506977..b0b0906f98 100644 --- a/docs/two-way-binding-helpers.html +++ b/docs/two-way-binding-helpers.html @@ -1,12 +1,14 @@ + + - Two-Way Binding Helpers | React - - + Two-way Binding Helpers - React + + @@ -44,31 +46,145 @@
-
+
+ Edit on GitHub +

+ Two-way Binding Helpers +

+
+ +
+

Note: +LinkedStateMixin is deprecated as of React v15. The recommendation is to explicitly set the value and change handler, instead of using LinkedStateMixin.

+
+ +

Importing

+
import LinkedStateMixin from 'react-addons-linked-state-mixin' // ES6
+var LinkedStateMixin = require('react-addons-linked-state-mixin') // ES5 with npm
+var LinkedStateMixin = React.addons.LinkedStateMixin; // ES5 with react-with-addons.js
+

Overview #

+

LinkedStateMixin is an easy way to express two-way binding with React.

+ +

In React, data flows one way: from owner to child. This is because data only flows one direction in the Von Neumann model of computing. You can think of it as "one-way data binding."

+ +

However, there are lots of applications that require you to read some data and flow it back into your program. For example, when developing forms, you'll often want to update some React state when you receive user input. Or perhaps you want to perform layout in JavaScript and react to changes in some DOM element size.

+ +

In React, you would implement this by listening to a "change" event, read from your data source (usually the DOM) and call setState() on one of your components. "Closing the data flow loop" explicitly leads to more understandable and easier-to-maintain programs. See our forms documentation for more information.

+ +

Two-way binding -- implicitly enforcing that some value in the DOM is always consistent with some React state -- is concise and supports a wide variety of applications. We've provided LinkedStateMixin: syntactic sugar for setting up the common data flow loop pattern described above, or "linking" some data source to React state.

+ +
+

Note:

+ +

LinkedStateMixin is just a thin wrapper and convention around the onChange/setState() pattern. It doesn't fundamentally change how data flows in your React application.

+
+

LinkedStateMixin: Before and After #

+

Here's a simple form example without using LinkedStateMixin:

+
var NoLink = React.createClass({
+  getInitialState: function() {
+    return {message: 'Hello!'};
+  },
+  handleChange: function(event) {
+    this.setState({message: event.target.value});
+  },
+  render: function() {
+    var message = this.state.message;
+    return <input type="text" value={message} onChange={this.handleChange} />;
+  }
+});
+
+

This works really well and it's very clear how data is flowing, however, with a lot of form fields it could get a bit verbose. Let's use LinkedStateMixin to save us some typing:

+
var WithLink = React.createClass({
+  mixins: [LinkedStateMixin],
+  getInitialState: function() {
+    return {message: 'Hello!'};
+  },
+  render: function() {
+    return <input type="text" valueLink={this.linkState('message')} />;
+  }
+});
+
+

LinkedStateMixin adds a method to your React component called linkState(). linkState() returns a valueLink object which contains the current value of the React state and a callback to change it.

+ +

valueLink objects can be passed up and down the tree as props, so it's easy (and explicit) to set up two-way binding between a component deep in the hierarchy and state that lives higher in the hierarchy.

+ +

Note that checkboxes have a special behavior regarding their value attribute, which is the value that will be sent on form submit if the checkbox is checked (defaults to on). The value attribute is not updated when the checkbox is checked or unchecked. For checkboxes, you should use checkedLink instead of valueLink: + +<input type="checkbox" checkedLink={this.linkState('booleanValue')} /> +

+

Under the Hood #

+

There are two sides to LinkedStateMixin: the place where you create the valueLink instance and the place where you use it. To prove how simple LinkedStateMixin is, let's rewrite each side separately to be more explicit.

+

valueLink Without LinkedStateMixin #

var WithoutMixin = React.createClass({
+  getInitialState: function() {
+    return {message: 'Hello!'};
+  },
+  handleChange: function(newValue) {
+    this.setState({message: newValue});
+  },
+  render: function() {
+    var valueLink = {
+      value: this.state.message,
+      requestChange: this.handleChange
+    };
+    return <input type="text" valueLink={valueLink} />;
+  }
+});
+
+

As you can see, valueLink objects are very simple objects that just have a value and requestChange prop. And LinkedStateMixin is similarly simple: it just populates those fields with a value from this.state and a callback that calls this.setState().

+

LinkedStateMixin Without valueLink #

var LinkedStateMixin = require('react-addons-linked-state-mixin');
+
+var WithoutLink = React.createClass({
+  mixins: [LinkedStateMixin],
+  getInitialState: function() {
+    return {message: 'Hello!'};
+  },
+  render: function() {
+    var valueLink = this.linkState('message');
+    var handleChange = function(e) {
+      valueLink.requestChange(e.target.value);
+    };
+    return <input type="text" value={valueLink.value} onChange={handleChange} />;
+  }
+});
+
+

The valueLink prop is also quite simple. It simply handles the onChange event and calls this.props.valueLink.requestChange() and also uses this.props.valueLink.value instead of this.props.value. That's it!

+ + +
+ + ← Prev + + + Next → + +
+
+ - - - - + + + + - - - - - - - @@ -433,136 +419,57 @@
+ - -
- Edit on GitHub -

- Two-Way Binding Helpers -

-
- -

ReactLink is an easy way to express two-way binding with React.

- -
-

Note:

- -

ReactLink is deprecated as of React v15. The recommendation is to explicitly set the value and change handler, instead of using ReactLink.

-
- -

In React, data flows one way: from owner to child. This is because data only flows one direction in the Von Neumann model of computing. You can think of it as "one-way data binding."

- -

However, there are lots of applications that require you to read some data and flow it back into your program. For example, when developing forms, you'll often want to update some React state when you receive user input. Or perhaps you want to perform layout in JavaScript and react to changes in some DOM element size.

- -

In React, you would implement this by listening to a "change" event, read from your data source (usually the DOM) and call setState() on one of your components. "Closing the data flow loop" explicitly leads to more understandable and easier-to-maintain programs. See our forms documentation for more information.

- -

Two-way binding -- implicitly enforcing that some value in the DOM is always consistent with some React state -- is concise and supports a wide variety of applications. We've provided ReactLink: syntactic sugar for setting up the common data flow loop pattern described above, or "linking" some data source to React state.

- -
-

Note:

- -

ReactLink is just a thin wrapper and convention around the onChange/setState() pattern. It doesn't fundamentally change how data flows in your React application.

-
-

ReactLink: Before and After #

-

Here's a simple form example without using ReactLink:

-
var NoLink = React.createClass({
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  handleChange: function(event) {
-    this.setState({message: event.target.value});
-  },
-  render: function() {
-    var message = this.state.message;
-    return <input type="text" value={message} onChange={this.handleChange} />;
-  }
-});
-
-

This works really well and it's very clear how data is flowing, however, with a lot of form fields it could get a bit verbose. Let's use ReactLink to save us some typing:

-
var LinkedStateMixin = require('react-addons-linked-state-mixin');
-
-var WithLink = React.createClass({
-  mixins: [LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    return <input type="text" valueLink={this.linkState('message')} />;
-  }
-});
-
-

LinkedStateMixin adds a method to your React component called linkState(). linkState() returns a ReactLink object which contains the current value of the React state and a callback to change it.

- -

ReactLink objects can be passed up and down the tree as props, so it's easy (and explicit) to set up two-way binding between a component deep in the hierarchy and state that lives higher in the hierarchy.

- -

Note that checkboxes have a special behavior regarding their value attribute, which is the value that will be sent on form submit if the checkbox is checked (defaults to on). The value attribute is not updated when the checkbox is checked or unchecked. For checkboxes, you should use checkedLink instead of valueLink: - -<input type="checkbox" checkedLink={this.linkState('booleanValue')} /> -

-

Under the Hood #

-

There are two sides to ReactLink: the place where you create the ReactLink instance and the place where you use it. To prove how simple ReactLink is, let's rewrite each side separately to be more explicit.

-

ReactLink Without LinkedStateMixin #

var WithoutMixin = React.createClass({
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  handleChange: function(newValue) {
-    this.setState({message: newValue});
-  },
-  render: function() {
-    var valueLink = {
-      value: this.state.message,
-      requestChange: this.handleChange
-    };
-    return <input type="text" valueLink={valueLink} />;
-  }
-});
-
-

As you can see, ReactLink objects are very simple objects that just have a value and requestChange prop. And LinkedStateMixin is similarly simple: it just populates those fields with a value from this.state and a callback that calls this.setState().

-

ReactLink Without valueLink #

var LinkedStateMixin = require('react-addons-linked-state-mixin');
-
-var WithoutLink = React.createClass({
-  mixins: [LinkedStateMixin],
-  getInitialState: function() {
-    return {message: 'Hello!'};
-  },
-  render: function() {
-    var valueLink = this.linkState('message');
-    var handleChange = function(e) {
-      valueLink.requestChange(e.target.value);
-    };
-    return <input type="text" value={valueLink.value} onChange={handleChange} />;
-  }
-});
-
-

The valueLink prop is also quite simple. It simply handles the onChange event and calls this.props.valueLink.requestChange() and also uses this.props.valueLink.value instead of this.props.value. That's it!

- - -
- - ← Prev - - - Next → - -
-
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
- -
+ + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+
+ Edit on GitHub +

+ Typechecking With PropTypes +

+
+ +

As your app grows, you can catch a lot of bugs with typechecking. For some applications, you can use JavaScript extensions like Flow or TypeScript to typecheck your whole application. But even if you don't use those, React has some built-in typechecking abilities. To run typechecking on the props for a component, you can assign the special propTypes property:

+
class Greeting extends React.Component {
+  render() {
+    return (
+      <h1>Hello, {this.props.name}</h1>
+    );
+  }
+}
+
+Greeting.propTypes = {
+  name: React.PropTypes.string
+};
+
+

React.PropTypes exports a range of validators that can be used to make sure the data you receive is valid. In this example, we're using React.PropTypes.string. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. For performance reasons, propTypes is only checked in development mode.

+

React.PropTypes #

+

Here is an example documenting the different validators provided:

+
MyComponent.propTypes = {
+  // You can declare that a prop is a specific JS primitive. By default, these
+  // are all optional.
+  optionalArray: React.PropTypes.array,
+  optionalBool: React.PropTypes.bool,
+  optionalFunc: React.PropTypes.func,
+  optionalNumber: React.PropTypes.number,
+  optionalObject: React.PropTypes.object,
+  optionalString: React.PropTypes.string,
+  optionalSymbol: React.PropTypes.symbol,
+
+  // Anything that can be rendered: numbers, strings, elements or an array
+  // (or fragment) containing these types.
+  optionalNode: React.PropTypes.node,
+
+  // A React element.
+  optionalElement: React.PropTypes.element,
+
+  // You can also declare that a prop is an instance of a class. This uses
+  // JS's instanceof operator.
+  optionalMessage: React.PropTypes.instanceOf(Message),
+
+  // You can ensure that your prop is limited to specific values by treating
+  // it as an enum.
+  optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
+
+  // An object that could be one of many types
+  optionalUnion: React.PropTypes.oneOfType([
+    React.PropTypes.string,
+    React.PropTypes.number,
+    React.PropTypes.instanceOf(Message)
+  ]),
+
+  // An array of a certain type
+  optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
+
+  // An object with property values of a certain type
+  optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
+
+  // An object taking on a particular shape
+  optionalObjectWithShape: React.PropTypes.shape({
+    color: React.PropTypes.string,
+    fontSize: React.PropTypes.number
+  }),
+
+  // You can chain any of the above with `isRequired` to make sure a warning
+  // is shown if the prop isn't provided.
+  requiredFunc: React.PropTypes.func.isRequired,
+
+  // A value of any data type
+  requiredAny: React.PropTypes.any.isRequired,
+
+  // You can also specify a custom validator. It should return an Error
+  // object if the validation fails. Don't `console.warn` or throw, as this
+  // won't work inside `oneOfType`.
+  customProp: function(props, propName, componentName) {
+    if (!/matchme/.test(props[propName])) {
+      return new Error(
+        'Invalid prop `' + propName + '` supplied to' +
+        ' `' + componentName + '`. Validation failed.'
+      );
+    }
+  },
+
+  // You can also supply a custom validator to `arrayOf` and `objectOf`.
+  // It should return an Error object if the validation fails. The validator
+  // will be called for each key in the array or object. The first two
+  // arguments of the validator are the array or object itself, and the
+  // current item's key.
+  customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
+    if (!/matchme/.test(propValue[key])) {
+      return new Error(
+        'Invalid prop `' + propFullName + '` supplied to' +
+        ' `' + componentName + '`. Validation failed.'
+      );
+    }
+  })
+};
+

Requiring Single Children #

+

With React.PropTypes.element you can specify that only a single child can be passed to a component as children.

+
class MyComponent extends React.Component {
+  render() {
+    // This must be exactly one element or it will warn.
+    var children = this.props.children;
+    return (
+      <div>
+        {children}
+      </div>
+    );
+  }
+}
+
+MyComponent.propTypes = {
+  children: React.PropTypes.element.isRequired
+};
+

Default Prop Values #

+

You can define default values for your props by assigning to the special defaultProps property:

+
class Greeting extends React.Component {
+  render() {
+    return (
+      <h1>Hello, {this.props.name}</h1>
+    );
+  }
+}
+
+// Specifies the default values for props:
+Greeting.defaultProps = {
+  name: 'Stranger'
+};
+
+// Renders "Hello, Stranger":
+ReactDOM.render(
+  <Greeting />,
+  document.getElementById('example')
+);
+
+

The defaultProps will be used to ensure that this.props.name will have a value if it was not specified by the parent component. The propTypes typechecking happens after defaultProps are resolved, so typechecking will also apply to the defaultProps.

+ + +
+ + +
+
+ + + +
+ + + + +
+ +
+ + + diff --git a/docs/update-it-IT.html b/docs/update-it-IT.html deleted file mode 100644 index 56a525c6d9..0000000000 --- a/docs/update-it-IT.html +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - Helper per l'Immutabilità | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Helper per l'Immutabilità -

-
- -

React ti permette di usare qualunque stile per la gestione dei dati che desideri, incluso la mutazione. Tuttavia, se puoi usare dati immutabili in parti critiche per le prestazioni della tua applicazione è facile implementare rapidamente un metodo shouldComponentUpdate() che aumenta significativamente la velocità della tua applicazione.

- -

Avere a che fare con dati immutabili in JavaScript è più difficile che in linguaggi progettati a tale scopo, come Clojure. Tuttavia, abbiamo fornito un semplice helper per l'immutabilità, update(), che rende avere a che fare con questo tipo di dati molto più semplice, senza cambiare fondamentalmente la rappresentazione dei tuoi dati. Se puoi anche dare un'occhiata alla libreria Immutable-js di Facebook e la sezione Prestazioni Avanzate per maggiori dettagli su Immutable-js.

-

L'idea fondamentale #

-

Se muti i tuoi dati nella seguente maniera:

-
myData.x.y.z = 7;
-// oppure...
-myData.a.b.push(9);
-
-

non hai modo di determinare quali dati siano cambiati dal momento che la copia precedente è stata sovrascritta. Invece, devi creare una nuova copia di myData e cambiare solo le parti che vanno cambiate. Allora puoi confrontare la vecchia copia di myData con la nuova in shouldComponentUpdate() usando l'operatore di uguaglianza stretta ===:

-
var newData = deepCopy(myData);
-newData.x.y.z = 7;
-newData.a.b.push(9);
-
-

Sfortunatamente, le copie profonde sono costose, e a volte impossibili. Puoi alleviare questa limitazione copiando soltanto gli oggetti che devono essere cambiati e riutilizzando gli oggetti che nonsono cambiati. Sfortunatamente, nel JavaScript odierno questa può essere un'operazione difficoltosa:

-
var newData = extend(myData, {
-  x: extend(myData.x, {
-    y: extend(myData.x.y, {z: 7}),
-  }),
-  a: extend(myData.a, {b: myData.a.b.concat(9)})
-});
-
-

Mentre questo codice ha prestazioni accettabili (dal momento che effettua soltanto una copia superficiale di log n oggetti e riutilizza i rimanenti), è una gran scocciatura da scrivere. Guarda quanta ripetizione! Questo non è soltanto fastidioso, ma offre una grande superficie di attacco per i bachi.

- -

update() fornisce un semplice zucchero sintattico attorno a questo pattern per rendere più semplice la scrittura di questo codice. Questo codice diventa:

-
var newData = React.addons.update(myData, {
-  x: {y: {z: {$set: 7}}},
-  a: {b: {$push: [9]}}
-});
-
-

Mentre la sintassi richiede qualche tempo per abituarsi (anche se è ispirata dal linguaggio di query di MongoDB) non c'è ridondanza, può essere analizzato staticamente e non richiede la scrittura di più codice della versione mutativa.

- -

Le chiavi con il prefisso $ sono chiamate comandi. La struttura dati che stanno "mutando" viene chiamata bersaglio.

-

Comandi disponibili #

-
    -
  • {$push: array} invoca push() sul bersagio passando ciascun elemento di array.
  • -
  • {$unshift: array} invoca unshift() sul bersagio passando ciascun elemento di array.
  • -
  • {$splice: array of arrays} per ogni elemento di arrays invoca splice() sul bersaglio con i parametri forniti dall'elemento.
  • -
  • {$set: any} sostituisce l'intero bersaglio.
  • -
  • {$merge: object} unisce le chiavi di object con il bersaglio.
  • -
  • {$apply: function} passa il valore attuale alla funzione e lo aggiorna con il nuovo valore da essa restituito.
  • -
-

Esempi #

Semplice inserimento in coda #

var initialArray = [1, 2, 3];
-var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
-
-

initialArray is still [1, 2, 3].

-

Collezioni annidate #

var collection = [1, 2, {a: [12, 17, 15]}];
-var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
-// => [1, 2, {a: [12, 13, 14, 15]}]
-
-

Questo accede all'indice 2 di collection, alla chiave a, ed effettua lo splice di un elemento a partire dall'indice 1 (per rimuovere 17) e al contempo inserisce 13 e 14.

-

Aggiornare un valore basandosi sul suo valore attuale #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
-// => {a: 5, b: 6}
-// Questa è una forma equivalente, ma diventa prolissa per profonde collezioni annidate:
-var newObj2 = update(obj, {b: {$set: obj.b * 2}});
-

Unione (superficiale) #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/update-ja-JP.html b/docs/update-ja-JP.html deleted file mode 100644 index eb09edab27..0000000000 --- a/docs/update-ja-JP.html +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - 不変性のヘルパ | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 不変性のヘルパ -

-
- -

Reactは変化を含む、使用したいデータマネジメントのスタイルであればどういったものであっても使用することができます。しかし、アプリケーションの、パフォーマンスが重要な部分において不変なデータを使用できる場合は、速い shouldComponentUpdate() メソッドを実行して、簡単にアプリケーションのスピードを著しく速くすることができます。

- -

Clojureのような、不変なデータの扱いのためにデザインされた言語よりも、JavaScriptでそれを行うことは難しいです。しかし、単純な不変性のヘルパである、 update() が提供されています。それは、データがどのように表されるかということを基本的には変更すること なく データのタイプを扱うことを簡単にします。Immutable-jsについての詳細は、FacebookのImmutable-js進歩したパフォーマンスをご覧ください。

-

主要な考え #

-

もし変更する予定のデータが以下のようなものであれば、

-
myData.x.y.z = 7;
-// または...
-myData.a.b.push(9);
-
-

以前のコピーが上書きされるので、どのデータが変更されたか判断する方法はありません。代わりに、 myData の新しいコピーを作成する必要があり、変更される必要がある部分のみを変更します。それから、 myData の古いコピーと新しいコピーを shouldComponentUpdate() の中で以下のように、3つのイコールを使用して比較することができます。

-
var newData = deepCopy(myData);
-newData.x.y.z = 7;
-newData.a.b.push(9);
-
-

不幸なことに、ディープコピーはコストがかかり、不可能なときもあります。変更される必要があるオブジェクトをコピーすることと、変更されていないオブジェクトを再利用することによってのみ、これを代替することができます。不幸なことに、今日のJavaScriptでは、こういったことは面倒です。

-
var newData = extend(myData, {
-  x: extend(myData.x, {
-    y: extend(myData.x.y, {z: 7}),
-  }),
-  a: extend(myData.a, {b: myData.a.b.concat(9)})
-});
-
-

動きが速い一方で( log n オブジェクトのシャローコピーを作成し、残りを再利用するため)、記述するのには多くのコストがかかります。全てのコードの繰り返しを見てください。それらはつまらないものではなく、多くのバグの表面を提供します。

- -

update() はこのようなパターンにおいて、コードを簡単に記述するための単純な糖衣構文を提供します。そのコードは以下のようになります。

-
var newData = React.addons.update(myData, {
-  x: {y: {z: {$set: 7}}},
-  a: {b: {$push: [9]}}
-});
-
-

シンタックスは少し慣れが必要ですが(MongoDBのクエリ言語にインスパイアされているため)、冗長性はありません。静的に分析し、変更ができるバージョンと比べてタイプする量がすごく増えているわけではありません。

- -

$ から始まるキーは コマンド と呼ばれます。それらが「変更する」データ構造は ターゲット と呼ばれます。

-

使用できるコマンド #

-
    -
  • {$push: array} ターゲットに array の全ての要素を push() します。
  • -
  • {$unshift: array} ターゲットの array の全ての要素を unshift() します。
  • -
  • {$splice: array of arrays} arrays の全ての要素について、その要素によって提供されるパラメータのターゲットにおいて、 splice() を呼び出します。
  • -
  • {$set: any} ターゲットを完全に置き換えます。
  • -
  • {$merge: object} object のキーをターゲットとマージします。
  • -
  • {$apply: function} 現在の値を関数に渡し、返された新しい値によってそれを更新します。
  • -
-

#

単純なプッシュ #

var initialArray = [1, 2, 3];
-var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
-
-

initialArray[1, 2, 3] のままです。

-

ネストしたコレクション #

var collection = [1, 2, {a: [12, 17, 15]}];
-var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
-// => [1, 2, {a: [12, 13, 14, 15]}]
-
-

これは、 collection のインデックスが 2 である要素にアクセスし、インデックスが 1 である要素に( 17 を削除し)1314 を挿入することで繋ぎ合わせます。

-

現在の値に基づいて値を更新すること #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
-// => {a: 5, b: 6}
-// 以下は上と同義ですが、ネストが深いコレクションにとっては冗長になります。
-var newObj2 = update(obj, {b: {$set: obj.b * 2}});
-

(シャロー)マージ #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/update-ko-KR.html b/docs/update-ko-KR.html deleted file mode 100644 index 99206d565a..0000000000 --- a/docs/update-ko-KR.html +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - 불변성 헬퍼들 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 불변성 헬퍼들 -

-
- -

React에서는 mutation을 포함해 어떤 데이터 관리 방식도 사용하실 수 있습니다. 하지만 애플리케이션의 성능이 중요한 부분에서 불변의(immutable) 데이터를 사용할 수 있다면, 쉽게 빠른 shouldComponentUpdate() 메소드를 구현해 애플리케이션의 속도를 크게 향상시킬 수 있습니다.

- -

JavaScript에서 불변성의 데이터를 다루는 것은 Clojure같이 그것을 위해 디자인된 언어로 다루는 것보다는 어렵습니다. 하지만, React는 간단한 불변성 헬퍼를 제공합니다. update()는 이런 종류의 데이터를 근본적인 변화 없이 쉽게 다루도록 해줍니다. Immutable-js에 관한 좀 더 자세한 정보는 페이스북의 Immutable-js성능 심화을 참조하세요.

-

주요 아이디어 #

-

만약 데이터를 이렇게 변화시킨다면:

-
myData.x.y.z = 7;
-// or...
-myData.a.b.push(9);
-
-

이전의 카피가 덮어씌워진다면 어떤 자료가 바뀌었는지 알 방도가 없습니다. 대신에, myData의 새로운 카피를 만들고 오직 변화가 필요한 부분만 바꿀 필요가 있습니다. 그 다음 shouldComponentUpdate() 에서 myData의 이전 카피와 새로운 카피를 === 연산자를 사용하여 비교할 수 있습니다.

-
var newData = deepCopy(myData);
-newData.x.y.z = 7;
-newData.a.b.push(9);
-
-

하지만 깊은 복사는 비싸고, 가끔은 불가능하기도 합니다. 변화가 필요한 객체만 복제하고, 변화가 없는 객체는 다시 사용하는 방법으로만 비용을 줄일 수 있습니다. 안타깝지만 오늘날의 JavaScript에서는 그 방법이 성가실 수 있습니다:

-
var newData = extend(myData, {
-  x: extend(myData.x, {
-    y: extend(myData.x.y, {z: 7}),
-  }),
-  a: extend(myData.a, {b: myData.a.b.concat(9)})
-});
-
-

이것은 꽤 성능이 좋긴 하지만 (log n개의 객체만 얕은 복사하고, 나머지는 재사용하기 때문에), 일일히 쓰기엔 큰 고통이 따릅니다. 이 반복들을 보세요! 이건 짜증날 뿐만 아니라 버그들을 야기할수도 있습니다.

- -

update()는 이런 패턴 속에서 코드를 더 쉽게 쓸 수 있도록 편의 문법을 제공합니다. 코드는 이렇습니다:

-
var update = require('react-addons-update');
-
-var newData = update(myData, {
-  x: {y: {z: {$set: 7}}},
-  a: {b: {$push: [9]}}
-});
-
-

(MongoDB 쿼리 언어에서 영감을 받은) 이 문법에 익숙해지기에는 시간이 조금 걸리긴 하지만, 쓸모 없는 반복이 없고 정적분석이 가능할 뿐더러 변할 수 있는(mutative) 버전보다 더 많은 타이핑이 필요하지도 않습니다.

- -

$가 앞에 붙어있는 키들은 커맨드 라고 불립니다. "변하는" 자료 구조는 타겟 이라고 불립니다.

-

사용가능한 커맨드들 #

-
    -
  • {$push: array} 모든 아이템들을 타겟에 있는 arraypush()합니다.
  • -
  • {$unshift: array} 타겟속 array에 있는 모든 아이템들을 unshift()합니다.
  • -
  • {$splice: array of arrays} arrays 안의 각 아이템들이 splice()를 주어진 인자들을 사용해 호출하게 합니다.
  • -
  • {$set: any} 타겟 전체를 대체합니다.
  • -
  • {$merge: object} 타겟과 object의 키들을 병합합니다.
  • -
  • {$apply: function} 는 지금 값을 함수에 전달하고 새로운 리턴 값으로 업데이트합니다.
  • -
-

예제 #

간단한 push #

var initialArray = [1, 2, 3];
-var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
-
-

initialArray 은 여전히 [1, 2, 3] 입니다.

-

중첩된 컬렉션 #

var collection = [1, 2, {a: [12, 17, 15]}];
-var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
-// => [1, 2, {a: [12, 13, 14, 15]}]
-
-

이것은 collection의 인덱스 2의 키 a에 접근해, 인덱스 1에 있는 한 아이템을 접합(splice)해서(17를 제거하고) 13, 14를 추가합니다.

-

현재 상태에 의거해 값을 업데이트 #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
-// => {a: 5, b: 6}
-// 위의 것과 같은 동작을 합니다만, 깊게 중첩된 컬렉션들에서는 더 장황해 집니다.
-var newObj2 = update(obj, {b: {$set: obj.b * 2}});
-

(얕은) 합병 #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/update-zh-CN.html b/docs/update-zh-CN.html deleted file mode 100644 index 392f0357b3..0000000000 --- a/docs/update-zh-CN.html +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - immutability 助手 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- immutability 助手 -

-
- -

React 让你可以使用任何你想要的数据管理方式,包括 mutation。然而,如果你可以在你的应用的性能关键性部分里使用 immutable 数据,将会易于实现一个快速的 shouldComponentUpdate() 方法来显著加速你的 app。

- -

在 JavaScript 里处理 immutable 数据比在为此设计的语言中要难的多,比如 Clojure。然而,我们提供了一个简单的 immutability 助手,update(),它使处理这类数据容易多了,不用 根本性的改变你的数据的表达方式。你也同样可以看一看 Facebook 的 Immutable-jsAdvanced Performance 了解更多关于 Immutable-js 的信息。

-

主要的思路 #

-

如果你像这样变动数据:

-
myData.x.y.z = 7;
-// or...
-myData.a.b.push(9);
-
-

你将没有任何办法决定哪个数据被改变了,因为之前的拷贝已经被覆盖。作为替代,你需要创建一个新的 myData 的拷贝并且只修改需要改变的地方。然后你可以用三个等于在 shouldComponentUpdate() 里比较旧的 myData 拷贝与新的拷贝:

-
var newData = deepCopy(myData);
-newData.x.y.z = 7;
-newData.a.b.push(9);
-
-

不幸的是,深拷贝很昂贵,并且有时候不可能。你可以通过仅仅拷贝需要被改变和重用没有改变的对象来缓解这个情况。不幸的是,在当今的 JavaScript 里这会很笨重:

-
var newData = extend(myData, {
-  x: extend(myData.x, {
-    y: extend(myData.x.y, {z: 7}),
-  }),
-  a: extend(myData.a, {b: myData.a.b.concat(9)})
-});
-
-

虽然这相当高性能(因为只对 log n 的对象进行了浅拷贝并重用了剩下的),但它写起来很痛苦。看看所有重复的代码!这不仅仅是烦人的,同时也提供了一大片 bugs 区域。

- -

update() 提供了这个模式的简单语法糖来使写这类代码更容易。上面的代码变成:

-
var update = require('react-addons-update');
-
-var newData = update(myData, {
-  x: {y: {z: {$set: 7}}},
-  a: {b: {$push: [9]}}
-});
-
-

虽然这个语法需要花一些时间来适应(它的灵感来自于 MongoDB's query language),但是没有冗余,它可静态分析并且没有 mutative 版本那么多键入。

- -

$-前缀的 keys 被称为 命令。被 "变动的" 数据结构被称为 目标

-

有效的命令 #

-
    -
  • {$push: array} 在目标上 push() 所有 array 里的项目。
  • -
  • {$unshift: array} 在目标上 unshift() 所有 array 里的项目。
  • -
  • {$splice: array of arrays} 在目标上对于每一个 arrays 里的项目使用项目提供的参数调用 splice()
  • -
  • {$set: any} 整个替换目标.
  • -
  • {$merge: object} 合并 目标和 object 的 keys.
  • -
  • {$apply: function} 传递当前的值给 function 并用返回值更新它。
  • -
-

例子 #

简单的 push #

var initialArray = [1, 2, 3];
-var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
-
-

initialArray is still [1, 2, 3].

-

嵌套的 collections #

var collection = [1, 2, {a: [12, 17, 15]}];
-var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
-// => [1, 2, {a: [12, 13, 14, 15]}]
-
-

本例访问了 collection2索引下的键a,并且拼接了一个从索引1开始(移除17)并插入1314的项目。

-

基于当前的值更新新值 #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
-// => {a: 5, b: 6}
-// This is equivalent, but gets verbose for deeply nested collections:
-var newObj2 = update(obj, {b: {$set: obj.b * 2}});
-

(浅) 合并 #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/update.html b/docs/update.html index 5a90612eb3..58c03dca42 100644 --- a/docs/update.html +++ b/docs/update.html @@ -1,12 +1,14 @@ + + - Immutability Helpers | React - - + Immutability Helpers - React + + @@ -44,31 +46,116 @@
-
+
+ Edit on GitHub +

+ Immutability Helpers +

+
+ +
+

Note: +update is a legacy add-on. Use kolodny/immutability-helper instead.

+
+ +

Importing

+
import update from 'react-addons-update'; // ES6
+var update = require('react-addons-update'); // ES5 with npm
+var update = React.addons.update; // ES5 with react-with-addons.js
+

Overview #

+

React lets you use whatever style of data management you want, including mutation. However, if you can use immutable data in performance-critical parts of your application it's easy to implement a fast shouldComponentUpdate() method to significantly speed up your app.

+ +

Dealing with immutable data in JavaScript is more difficult than in languages designed for it, like Clojure. However, we've provided a simple immutability helper, update(), that makes dealing with this type of data much easier, without fundamentally changing how your data is represented. You can also take a look at Facebook's Immutable-js and the Advanced Performance section for more detail on Immutable-js.

+

The Main Idea #

+

If you mutate data like this:

+
myData.x.y.z = 7;
+// or...
+myData.a.b.push(9);
+
+

You have no way of determining which data has changed since the previous copy has been overwritten. Instead, you need to create a new copy of myData and change only the parts of it that need to be changed. Then you can compare the old copy of myData with the new one in shouldComponentUpdate() using triple-equals:

+
var newData = deepCopy(myData);
+newData.x.y.z = 7;
+newData.a.b.push(9);
+
+

Unfortunately, deep copies are expensive, and sometimes impossible. You can alleviate this by only copying objects that need to be changed and by reusing the objects that haven't changed. Unfortunately, in today's JavaScript this can be cumbersome:

+
var newData = extend(myData, {
+  x: extend(myData.x, {
+    y: extend(myData.x.y, {z: 7}),
+  }),
+  a: extend(myData.a, {b: myData.a.b.concat(9)})
+});
+
+

While this is fairly performant (since it only makes a shallow copy of log n objects and reuses the rest), it's a big pain to write. Look at all the repetition! This is not only annoying, but also provides a large surface area for bugs.

+

update() #

+

update() provides simple syntactic sugar around this pattern to make writing this code easier. This code becomes:

+
import update from 'react-addons-update';
+
+var newData = update(myData, {
+  x: {y: {z: {$set: 7}}},
+  a: {b: {$push: [9]}}
+});
+
+

While the syntax takes a little getting used to (though it's inspired by MongoDB's query language) there's no redundancy, it's statically analyzable and it's not much more typing than the mutative version.

+ +

The $-prefixed keys are called commands. The data structure they are "mutating" is called the target.

+

Available Commands #

+
    +
  • {$push: array} push() all the items in array on the target.
  • +
  • {$unshift: array} unshift() all the items in array on the target.
  • +
  • {$splice: array of arrays} for each item in arrays call splice() on the target with the parameters provided by the item.
  • +
  • {$set: any} replace the target entirely.
  • +
  • {$merge: object} merge the keys of object with the target.
  • +
  • {$apply: function} passes in the current value to the function and updates it with the new returned value.
  • +
+

Examples #

Simple push #

var initialArray = [1, 2, 3];
+var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
+
+

initialArray is still [1, 2, 3].

+

Nested collections #

var collection = [1, 2, {a: [12, 17, 15]}];
+var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
+// => [1, 2, {a: [12, 13, 14, 15]}]
+
+

This accesses collection's index 2, key a, and does a splice of one item starting from index 1 (to remove 17) while inserting 13 and 14.

+

Updating a value based on its current one #

var obj = {a: 5, b: 3};
+var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
+// => {a: 5, b: 6}
+// This is equivalent, but gets verbose for deeply nested collections:
+var newObj2 = update(obj, {b: {$set: obj.b * 2}});
+

(Shallow) Merge #

var obj = {a: 5, b: 3};
+var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
+
+ +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,103 +390,57 @@
+ - -
- Edit on GitHub -

- Immutability Helpers -

-
- -

React lets you use whatever style of data management you want, including mutation. However, if you can use immutable data in performance-critical parts of your application it's easy to implement a fast shouldComponentUpdate() method to significantly speed up your app.

- -

Dealing with immutable data in JavaScript is more difficult than in languages designed for it, like Clojure. However, we've provided a simple immutability helper, update(), that makes dealing with this type of data much easier, without fundamentally changing how your data is represented. You can also take a look at Facebook's Immutable-js and the Advanced Performance section for more detail on Immutable-js.

-

The main idea #

-

If you mutate data like this:

-
myData.x.y.z = 7;
-// or...
-myData.a.b.push(9);
-
-

You have no way of determining which data has changed since the previous copy has been overwritten. Instead, you need to create a new copy of myData and change only the parts of it that need to be changed. Then you can compare the old copy of myData with the new one in shouldComponentUpdate() using triple-equals:

-
var newData = deepCopy(myData);
-newData.x.y.z = 7;
-newData.a.b.push(9);
-
-

Unfortunately, deep copies are expensive, and sometimes impossible. You can alleviate this by only copying objects that need to be changed and by reusing the objects that haven't changed. Unfortunately, in today's JavaScript this can be cumbersome:

-
var newData = extend(myData, {
-  x: extend(myData.x, {
-    y: extend(myData.x.y, {z: 7}),
-  }),
-  a: extend(myData.a, {b: myData.a.b.concat(9)})
-});
-
-

While this is fairly performant (since it only makes a shallow copy of log n objects and reuses the rest), it's a big pain to write. Look at all the repetition! This is not only annoying, but also provides a large surface area for bugs.

- -

update() provides simple syntactic sugar around this pattern to make writing this code easier. This code becomes:

-
var update = require('react-addons-update');
-
-var newData = update(myData, {
-  x: {y: {z: {$set: 7}}},
-  a: {b: {$push: [9]}}
-});
-
-

While the syntax takes a little getting used to (though it's inspired by MongoDB's query language) there's no redundancy, it's statically analyzable and it's not much more typing than the mutative version.

- -

The $-prefixed keys are called commands. The data structure they are "mutating" is called the target.

-

Available commands #

-
    -
  • {$push: array} push() all the items in array on the target.
  • -
  • {$unshift: array} unshift() all the items in array on the target.
  • -
  • {$splice: array of arrays} for each item in arrays call splice() on the target with the parameters provided by the item.
  • -
  • {$set: any} replace the target entirely.
  • -
  • {$merge: object} merge the keys of object with the target.
  • -
  • {$apply: function} passes in the current value to the function and updates it with the new returned value.
  • -
-

Examples #

Simple push #

var initialArray = [1, 2, 3];
-var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
-
-

initialArray is still [1, 2, 3].

-

Nested collections #

var collection = [1, 2, {a: [12, 17, 15]}];
-var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
-// => [1, 2, {a: [12, 13, 14, 15]}]
-
-

This accesses collection's index 2, key a, and does a splice of one item starting from index 1 (to remove 17) while inserting 13 and 14.

-

Updating a value based on its current one #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
-// => {a: 5, b: 6}
-// This is equivalent, but gets verbose for deeply nested collections:
-var newObj2 = update(obj, {b: {$set: obj.b * 2}});
-

(Shallow) merge #

var obj = {a: 5, b: 3};
-var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
-
- -
- - ← Prev - - - Next → - -
-
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
- -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Videos -

-
- -

Rethinking best practices - JSConf.eu #

- - -

"At Facebook and Instagram, we’re trying to push the limits of what’s possible on the web with React. My talk will start with a brief introduction to the framework, and then dive into three controversial topics: Throwing out the notion of templates and building views with JavaScript, “re-rendering” your entire application when your data changes, and a lightweight implementation of the DOM and events." -- Pete Hunt

- -
-

Thinking in react - tagtree.tv #

-

A tagtree.tv video conveying the principles of Thinking in React while building a simple app -

- -
-

Secrets of the Virtual DOM - MtnWest JS #

- - -

"In this talk I’ll be discussing why we built a virtual DOM, how it compares to other systems, and its relevance to the future of browser technologies." -- Pete Hunt

- -
-

Going big with React #

-

"On paper, all those JS frameworks look promising: clean implementations, quick code design, flawless execution. But what happens when you stress test Javascript? What happens when you throw 6 megabytes of code at it? In this talk, we'll investigate how React performs in a high stress situation, and how it has helped our team build safe code on a massive scale." -

- -
-

CodeWinds #

-

Pete Hunt talked with Jeff Barczewski about React in CodeWinds Episode 4. -

- -
-02:08 - What is React and why use it?
-03:08 - The symbiotic relationship of ClojureScript and React
-04:54 - The history of React and why it was created
-09:43 - Updating web page with React without using data binding
-13:11 - Using the virtual DOM to change the browser DOM
-13:57 - Programming with React, render targets HTML, canvas, other
-16:45 - Working with designers. Contrasted with Ember and AngularJS
-21:45 - JSX Compiler bridging HTML and React javascript
-23:50 - Autobuilding JSX and in browser tools for React
-24:50 - Tips and tricks to working with React, getting started
-
-27:17 - Rendering HTML on the server with Node.js. Rendering backends
-29:20 - React evolved through survival of the fittest at Facebook
-30:15 - Ideas for having state on server and client, using web sockets.
-32:05 - React-multiuser - distributed shared mutable state using Firebase
-33:03 - Better debugging with React using the state transitions, replaying events
-34:08 - Differences from Web Components
-34:25 - Notable companies using React
-35:16 - Could a React backend plugin be created to target PDF?
-36:30 - Future of React, what's next?
-39:38 - Contributing and getting help
-
- -

Read the episode notes

- -
-

JavaScript Jabber #

-

Pete Hunt and Jordan Walke talked about React in JavaScript Jabber 73. -

- -
-01:34 – Pete Hunt Introduction
-02:45 – Jordan Walke Introduction
-04:15 – React
-06:38 – 60 Frames Per Second
-09:34 – Data Binding
-12:31 – Performance
-17:39 – Diffing Algorithm
-19:36 – DOM Manipulation -
-23:06 – Supporting node.js
-24:03 – rendr
-26:02 – JSX
-30:31 – requestAnimationFrame
-34:15 – React and Applications
-38:12 – React Users Khan Academy
-39:53 – Making it work -
- -

Read the full transcript

- -
-

Introduction to React.js - Facebook Seattle #

- - -

By Tom Occhino and Jordan Walke

- -
-

Backbone + React + Middleman Screencast #

- - -

Backbone is a great way in interface a REST API with React. This screencast shows how to integrate the two using Backbone-React-Component. Middleman is the framework used in this example but could easily be replaced with other frameworks. A supported template of this can be found here. -- Open Minded Innovations

- -
-

Developing User Interfaces With React - Super VanJS #

- - -

By Steven Luscher

- -
-

Introduction to React - LAWebSpeed meetup #

- - -

by Stoyan Stefanov

- -
-

React, or how to make life simpler - FrontEnd Dev Conf '14 #

- - -

In Russian by Alexander Solovyov

- -
-

"Functional DOM programming" - Meteor DevShop 11 #

- - -
-

"Rethinking Web App Development at Facebook" - Facebook F8 Conference 2014 #

- - -
-

React and Flux: Building Applications with a Unidirectional Data Flow - Forward JS 2014 #

- - -

Facebook engineers Bill Fisher and Jing Chen talk about Flux and React, and how using an application architecture with a unidirectional data flow cleans up a lot of their code.

- -
-

Server-Side Rendering of Isomorphic Apps at SoundCloud #

- - -

Walk-through by Andres Suarez on how SoundCloud is using React and Flux for server-side rendering.

- -

Slides and sample code

- -
-

Introducing React Native (+Playlist) - React.js Conf 2015 #

- - -

Tom Occhino reviews the past and present of React in 2015, and teases where it's going next.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/webcomponents-zh-CN.html b/docs/web-components.html similarity index 50% rename from docs/webcomponents-zh-CN.html rename to docs/web-components.html index 083ef51559..a0d0d27abb 100644 --- a/docs/webcomponents-zh-CN.html +++ b/docs/web-components.html @@ -1,14 +1,16 @@ + + - Web Components | React - - + Web Components - React + + - + @@ -44,31 +46,88 @@
-
+
+ Edit on GitHub +

+ Web Components +

+
+ +

React and Web Components are built to solve different problems. Web Components provide strong encapsulation for reusable components, while React provides a declarative library that keeps the DOM in sync with your data. The two goals are complementary. As a developer, you are free to use React in your Web Components, or to use Web Components in React, or both.

+ +

Most people who use React don't use Web Components, but you may want to, especially if you are using third-party UI components that are written using Web Components.

+

Using Web Components in React #

class HelloMessage extends React.Component {
+  render() {
+    return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
+  }
+}
+
+
+

Note:

+ +

Web Components often expose an imperative API. For instance, a video Web Component might expose play() and pause() functions). To access the imperative APIs of a Web Component, you will need to use a ref to interact with the DOM node directly. If you are using third-party Web Components, the best solution is to write a React component that behaves as a wrapper for your Web Component.

+ +

Events emitted by a Web Component may not properly propagate through a React render tree. +You will need to manually attach event handlers to handle these events within your React components.

+
+ +

One common confusion is that Web Components use "class" instead of "className".

+
function BrickFlipbox() {
+  return (
+    <brick-flipbox class="demo" ref="foo">
+      <div>front</div>
+      <div>back</div>
+    </brick-flipbox>
+  );
+}
+

Using React in your Web Components #

var proto = Object.create(HTMLElement.prototype, {
+  attachedCallback: {
+    value: function() {
+      var mountPoint = document.createElement('span');
+      this.createShadowRoot().appendChild(mountPoint);
+
+      var name = this.getAttribute('name');
+      var url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
+      ReactDOM.render(<a href={url}>{name}</a>, mountPoint);
+    }
+  }
+});
+document.registerElement('x-search', {prototype: proto});
+
+

You can also check out this complete Web Components example on GitHub.

+ + +
+ + +
+
+ - - - - + + + + - - - - - - - @@ -433,78 +362,57 @@
+ - -
- Edit on GitHub -

- Web Components -

-
- -

因为React和Web组件是用来解决不同问题的, 试图比较两者将不可避免地导致似是而非的结论, 。Web组件为可复用组件提供了强大的封装, 而React则提供了一个使DOM与你的数据同步的声明式库。两者的目标是互补的;工程师可以混合使用这些技术。作为一个开发者,你可以在你的Web组件中使用React,或者在React中使用Web组件,或者两者一起使用。

-

在React中使用Web组件 #

class HelloMessage extends React.Component{
-  render() {
-    return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
-  }
-}
-
-
-

注意:

- -

两个组件系统的程序模型 (web 组件 与 react 组件) 区别在 -web组件通常暴露一个命令式的API (比如 一个 video web 组件可能暴露 play() -与 pause() 函数)。 因为web 组件是它们属性的声明式函数, -他们应该可以执行, 但是如果要访问命令式API的一个web组件, 你将需要在组件上附加一个引用 -并与DOM节点直接交互。如果你在使用第三方web组件, -我们推荐你写一个React组件作为你的web组件的封装。

- -

当前,一个由web组件触发的事件可能不能准确地在React渲染树中传递。 -你将需要手动附加event handlers来在你的react组件中处理这些事件。

-
-

在Web 组件中使用React #

var proto = Object.create(HTMLElement.prototype, {
-  attachedCallback: {
-    value: function() {
-      var mountPoint = document.createElement('span');
-      this.createShadowRoot().appendChild(mountPoint);
-
-      var name = this.getAttribute('name');
-      var url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
-      ReactDOM.render(<a href={url}>{name}</a>, mountPoint);
-    }
-  }
-});
-document.registerElement('x-search', {prototype: proto});
-

完整样例 #

-

若要查看完整样例,请参照starter kit中的webcomponents例子。

- - -
- - ← Prev - - - Next → - -
-
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
- -
+ + + +
- - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Web Components -

-
- -

Trying to compare and contrast React with WebComponents inevitably results in specious conclusions, because the two libraries are built to solve different problems. WebComponents provide strong encapsulation for reusable components, while React provides a declarative library that keeps the DOM in sync with your data. The two goals are complementary; engineers can mix-and-match the technologies. As a developer, you are free to use React in your WebComponents, or to use WebComponents in React, or both.

-

Using Web Components in React #

class HelloMessage extends React.Component{
-  render() {
-    return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
-  }
-}
-
-
-

Note:

- -

The programming models of the two component systems (web components vs. react components) differ in that -web components often expose an imperative API (for instance, a video web component might expose play() -and pause() functions). To the extent that web components are declarative functions of their attributes, -they should work, but to access the imperative APIs of a web component, you will need to attach a ref to the -component and interact with the DOM node directly. If you are using third-party web components, the -recommended solution is to write a React component that behaves as a wrapper for your web component.

- -

At this time, events emitted by a web component may not properly propagate through a React render tree. -You will need to manually attach event handlers to handle these events within your React components.

-
-

Using React in your Web Components #

var proto = Object.create(HTMLElement.prototype, {
-  attachedCallback: {
-    value: function() {
-      var mountPoint = document.createElement('span');
-      this.createShadowRoot().appendChild(mountPoint);
-
-      var name = this.getAttribute('name');
-      var url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
-      ReactDOM.render(<a href={url}>{name}</a>, mountPoint);
-    }
-  }
-});
-document.registerElement('x-search', {prototype: proto});
-

Complete Example #

-

Check out the webcomponents example in the starter kit for a complete example.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/why-react-de-DE.html b/docs/why-react-de-DE.html deleted file mode 100644 index 401847df13..0000000000 --- a/docs/why-react-de-DE.html +++ /dev/null @@ -1,507 +0,0 @@ - - - - - - - Warum React? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Warum React? -

-
- -

React ist eine JavaScript-Bibliothek von Facebook und Instagram für Benutzeroberflächen. Man kann sich React als das V in MVC vorstellen.

- -

Wir haben React für folgende Aufgabe entwickelt: umfangreiche Anwendungen zu bauen, deren Daten sich zeitlich ändern.

-

Einfach #

-

Beschreibe, wie sich Deine App zu jedem gewünschten Zeitpunkt präsentieren soll und React kümmert sich um alle Benutzeroberflächen-Änderungen sobald sich die zugrundeliegenden Daten ändern.

-

Deklarativ #

-

Bei Datenveränderungen drückt React bildlich die "Aktualisieren"-Taste und versteht sich darauf, nur die veränderten Elemente zu erneuern.

-

Baue zusammensetzbare Komponenten #

-

React unterstützt die Entwicklung wiederverwendbarer Komponenten. Tatsächlich machst Du in React nichts anderes, als Komponenten zu bauen. Dank ihrer Kapselung erleichtern Komponenten die Wiederverwendung und das Testen von Code sowie die Trennung der Belange.

-

Gib' ihnen fünf Minuten #

-

React hinterfragt eine ganze Reihe konventioneller Standpunkte. Auf den ersten Blick mögen einige Ideen verrückt klingen. Gib' ihnen fünf Minuten während Du diese Anleitung liest; diese verrückten Ideen halfen dabei, tausende von Komponenten innerhalb und außerhalb von Facebook und Instagram zu entwickeln.

-

Erfahre mehr #

-

Erfahre mehr über unsere Motivation zur Entwicklung von React in diesem Blogeintrag.

- - -
- - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/why-react-it-IT.html b/docs/why-react-it-IT.html deleted file mode 100644 index 44d65d46f7..0000000000 --- a/docs/why-react-it-IT.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - Perché React? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Perché React? -

-
- -

React è una libreria JavaScript per creare interfacce utente scritta da Facebook e Instagram. A molti piace pensare a React come alla V di MVC.

- -

Abbiamo costruito React per risolvere un problema: costruire applicazioni di grandi dimensioni con dati che cambiano nel tempo.

-

Semplice #

-

Dichiara semplicemente come la tua app debba apparire in ogni istante, e React gestirà automaticamente tutti gli aggiornamenti della UI quando i dati sottostanti cambiano.

-

Dichiarativo #

-

Quando i dati cambiano, React preme idealmente il bottone "aggiorna", e sa come aggiornare soltanto le parti che sono cambiate.

-

Costruisci Componenti Componibili #

-

React è basato interamente sulla costruzione di componenti riutilizzabili. Infatti, con React l'unica cosa che fai è costruire componenti. Dal momento che sono così incapsulati, i componenti facilitano il riutilizzo del codice, la verifica e la separazione dei concetti.

-

Dagli Cinque Minuti #

-

React sfida molte convenzioni, e a prima vista alcune delle idee potrebbero sembrare folli. Dagli cinque minuti mentre leggi questa guida; quelle idee folli hanno funzionato per costruire migliaia di componenti sia dentro che fuori da Facebook e Instagram.

-

Per Approfondire #

-

Puoi approfondire le nostre motivazioni per la costruzione di React leggendo questo articolo del blog.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/why-react-ja-JP.html b/docs/why-react-ja-JP.html deleted file mode 100644 index 471eae6c31..0000000000 --- a/docs/why-react-ja-JP.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - なぜReactを使うのでしょうか? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- なぜReactを使うのでしょうか? -

-
- -

ReactはFacebookとInstagramによって作られたユーザーインターフェイスを構築するためのJavaScriptのライブラリです。 -多くの人がReactを MVCV だと考えています。 -私たちはReactをある1つの問題を解決するために使います。それは、 絶えず変化していくデータとともに大きなアプリケーションを構築する ことです。それを行うために、Reactは2つの主要な考えを持っています。

-

単純さ #

-

どのタイミングにおいても、アプリケーションがどのように見えるべきかを単純に表現し、Reactは根底にあるデータの変更があった場合に自動的に全てのUIを管理します。

-

叙述的 #

-

データが変わった時、Reactは概念的に「リフレッシュ」ボタンを押し、変わった箇所のみを検知します。

-

コンポーザブルなコンポーネントの構築 #

-

Reactは再利用可能なコンポーネントを構築するものです。実際、Reactを用いてあなたがする ただ1つの ことは、コンポーネントを構築することです。Reactは無駄な部分を省いてあるので、コンポーネントはコードの再利用、テスト、関心の分離を可能にします。

-

5分ください #

-

Reactは型にはまった知識にも挑戦し、ちらっと見ただけではおかしく見えるアイディアもあるでしょう。このガイドを読むのに5分ください 。それらのおかしく見えるアイディアはFacebookやInstagramの中と外の両方で何千ものコンポーネントを構築するために動いています。

-

更なる学習 #

-

このブログの投稿で、私たちがReactを構築するモチベーションについて更に学習することができます。

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/why-react-ko-KR.html b/docs/why-react-ko-KR.html deleted file mode 100644 index 18ef45f4f9..0000000000 --- a/docs/why-react-ko-KR.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - 왜 React인가? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 왜 React인가? -

-
- -

React는 페이스북과 인스타그램에서 사용자 인터페이스를 구성하기 위해 만들어진 라이브러리입니다. 많은 사람들은 React를 MVC 에서의 V 로 생각하는 경향이 있습니다.

- -

우리는 단 하나의 문제를 해결하기 위해 React를 만들었습니다: 지속해서 데이터가 변화하는 대규모 애플리케이션을 구축하기. 이 문제를 해결하기 위해, React는 두가지 컨셉을 도입했습니다.

-

단순함 #

-

당신의 애플리케이션이 특정 시점에 어떻게 보여야 할지를 단순히 표현하는 것만으로, 데이터가 변할 때 React는 자동으로 모든 UI 업데이트를 관리해줍니다.

-

선언적 문법 #

-

데이터가 변할 때 React는 "새로 고침" 버튼을 누르듯이 작동하며, 데이터의 바뀐 부분만을 업데이트할 수 있습니다.

-

구성적인 컴포넌트를 만드세요 #

-

React는 재사용 가능한 컴포넌트들을 만드는 데에 도움이 됩니다. 사실, React를 사용하면 단지 컴포넌트를 만드는 일만 하게 됩니다. 컴포넌트들은 잘 캡슐화되어 되어 있기 때문에, 컴포넌트들은 코드의 재사용성을 높이고, 테스트를 쉽게 해 주며, 관심 분리의 원칙(separation of concerns)을 지키게 해 줍니다.

-

5분만 투자하세요 #

-

React는 많은 관습적인 사고에 도전하며, 첫눈에 볼 때는 이상한 아이디어들의 모음이라고 생각할 수도 있습니다. 이 가이드를 읽기 위해 5분만 투자하세요; 그 이상한 아이디어들은 페이스북과 인스타그램 안팎의 수천 개의 컴포넌트들을 만드는 데에 사용되었기 때문입니다.

-

더 알아보기 #

-

이 블로그 포스트에서 React를 만든 우리의 동기에 대해 알아볼 수 있습니다.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/why-react-ru-RU.html b/docs/why-react-ru-RU.html deleted file mode 100644 index da1772a5d4..0000000000 --- a/docs/why-react-ru-RU.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - Почему именно React? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Почему именно React? -

-
- -

React — библиотека JavaScript для создания интерфейсов от команд Facebook и Instagram. Многие ассоциируют React с понятием View в паттерне MVC.

- -

Мы делали React, чтобы решить одну важную задачу: создавать действительно большие приложения с постоянно меняющимися данными.

-

Простота #

-

С React вы всегда точно знаете как будет выглядеть ваше приложение, ведь как только изменятся данные, он мгновенно отобразит эти изменения в интерфейсе.

-

Декларативность #

-

Как только состояние приложения изменится, React будто нажимает кнопку "обновить" и точно знает, какие части интерфейса надо поменять, а какие нет. Никаких дополнительных инструкций и команд, React сам отслеживает изменения данных и реагирует на них.

-

Создание компонентов, как строительных блоков приложения #

-

По сути, разработка на React целиком состоит в создании таких компонентов. С React вы только тем и занимаетесь, что пишете новые компоненты, те самые строительные блоки, из которых будет строиться приложение. А поскольку они хорошо инскапсулированы, их удобно использовать повторно даже в других проектах, плюс такой код проще тестировать.

-

Уделите этому 5 минут #

-

React бросает вызов многим устоявшимся идеям и правилам, и на первый взгляд, некоторые из его идей выглядят по меньшей мере странными. Уделите этому 5 минут пока читаете эту статью; эти безумные идеи нашли свое применение при создании тысяч компонентов не только для Facebook и Instagram, но и в других крупных проектах.

-

Узнай больше #

-

Вы можете больше узнать о причинах создания React отсюда.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/why-react-zh-CN.html b/docs/why-react-zh-CN.html deleted file mode 100644 index 9f6e6dba6e..0000000000 --- a/docs/why-react-zh-CN.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - 为什么使用 React? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 为什么使用 React? -

-
- -

React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。很多人选择将 React 认为是 MVC 中的 V(视图)。

- -

我们创造 React 是为了解决一个问题:构建随着时间数据不断变化的大规模应用程序

-

简单 #

-

仅仅只要表达出你的应用程序在任一个时间点应该呈现的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。

-

声明式 (Declarative) #

-

数据变化后,React 概念上与点击“刷新”按钮类似,但仅会更新变化的部分。

-

构建可组合的组件 #

-

React 都是关于构建可复用的组件。事实上,通过 React 你唯一要做的事情就是构建组件。得益于其良好的封装性,组件使代码复用、测试和关注分离(separation of concerns)更加简单。

-

给它5分钟的时间 #

-

React挑战了很多传统的知识,第一眼看上去可能很多想法有点疯狂。当你阅读这篇指南,请给它5分钟的时间;那些疯狂的想法已经帮助 Facebook 和 Instagram 从里到外创建了上千的组件了。

-

了解更多 #

-

你可以从这篇博客了解更多我们创造 React 的动机。

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/why-react-zh-TW.html b/docs/why-react-zh-TW.html deleted file mode 100644 index dea72e9d0e..0000000000 --- a/docs/why-react-zh-TW.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - Why React? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Why React? -

-
- -

React是Facebook和Instagram用來建立使用者介面的JavaScript函式庫. 很多人認為React就是處理 MVC架構中 V 的部份.

- -

我們建造React用來解決一個問題: 開發資料能隨時間頻繁更新的大型應用程式.

-

簡單(Simple) #

-

簡單意味著你所開發的應用程式外觀任何一部分都要能即時呈現, 並且當資料有所變動時React能自動管理所有UI的更新.

-

陳述(Declarative) #

-

當資料改變時, React概念上就像是點擊了 "刷新" 的按鈕, 並且知道只需更新有改變的部份.

-

建立可組合的元件(Composable Components) #

-

React就是在建造可重用的元件(Components). 事實上, 當你使用React時 唯一 在做的事就是建立元件(Components). 由於它們封裝性高,元件使得程式碼能夠易於重複使用, 測試, 並且容易做到讓關注點分離(separation of concerns easy).

-

指引(Give It Five Minutes) #

-

React挑戰了許多傳統的觀念, 第一次乍看之下這些構想可能看起來有點瘋狂. Give it five minutes 而當閱讀完這篇指引; 這些瘋狂的構想在Facebook和Instagram裡裡外外建立了數以千計的元件(components)之後被證明是可實行的.

-

更多學習資源 #

-

從這裡你能學習到更多建造React背後的動機 this blog post.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/why-react.html b/docs/why-react.html index 5d9703ecd7..792e552a0e 100644 --- a/docs/why-react.html +++ b/docs/why-react.html @@ -1,509 +1,10 @@ - - - - - - Why React? | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Why React? -

-
- -

React is a JavaScript library for creating user interfaces by Facebook and Instagram. Many people choose to think of React as the V in MVC.

- -

We built React to solve one problem: building large applications with data that changes over time.

-

Simple #

-

Simply express how your app should look at any given point in time, and React will automatically manage all UI updates when your underlying data changes.

-

Declarative #

-

When the data changes, React conceptually hits the "refresh" button, and knows to only update the changed parts.

-

Build Composable Components #

-

React is all about building reusable components. In fact, with React the only thing you do is build components. Since they're so encapsulated, components make code reuse, testing, and separation of concerns easy.

-

Give It Five Minutes #

-

React challenges a lot of conventional wisdom, and at first glance some of the ideas may seem crazy. Give it five minutes while reading this guide; those crazy ideas have worked for building thousands of components both inside and outside of Facebook and Instagram.

-

Learn More #

-

You can learn more about our motivations behind building React in this blog post.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/docs/working-with-the-browser-it-IT.html b/docs/working-with-the-browser-it-IT.html deleted file mode 100644 index 99f917ac4d..0000000000 --- a/docs/working-with-the-browser-it-IT.html +++ /dev/null @@ -1,582 +0,0 @@ - - - - - - - Lavorare con il Browser | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Lavorare con il Browser -

-
- -

React offre potenti astrazioni che ti liberano in molti casi dal compito di manipolare direttamente il DOM, ma a volte potresti avere bisogno di accedere alle API sottostanti, ad esempio per lavorare con una libreria di terze parti o altro codice preesistente.

-

Il DOM Virtuale #

-

React è così veloce perché non interagisce direttamente con il DOM. React gestisce una rappresentazione veloce del DOM in memoria. I metodi render() restituiscono una descrizione del DOM, e React può confrontare questa descrizione con la rappresentazione in memoria per calcolare la maniera più veloce di aggiornare il browser.

- -

In aggiunta, React implementa un intero sistema di eventi sintetici che fa in modo che tutti gli oggetti evento siano conformi alle specifiche W3C nonostante le incompatibilità dei browser, e ciascun evento si propaga in maniera consistente ed efficiente in ogni browser. Puoi anche utilizzare alcuni eventi HTML5 in IE8!

- -

Nella maggior parte dei casi è sufficiente rimanere nel mondo del "browser fittizio" di React poiché più efficiente e facile da concepire. Tuttavia, a volte potresti aver bisogno di accedere alle API sottostanti, ad esempio per lavorare con una libreria di terze parti come un plugin jQuery. React fornisce convenienti vie di fuga perché tu possa utilizzare direttamente le API DOM sottostanti.

-

I Ref e findDOMNode() #

-

Per interagire con il browser, avrai bisogno di un riferimento a un nodo DOM. Puoi assegnare un attributo ref a ciascun elemento, ciò ti permette di fare riferimento all'istanza di supporto del componente. Questo è utile se devi invocare funzioni imperative sul componente, oppure desideri accedere ai nodi DOM sottostanti. Per saperne di piu sui ref, incluso la maniera di usarli con efficacia, leggi la nostra documentazione riferimenti a componenti.

-

Ciclo di Vita del Componente #

-

I componenti hanno tree fasi principali del ciclo di vita:

- -
    -
  • Montaggio: Un componente sta venendo inserito nel DOM.
  • -
  • Aggiornamento: Viene effettuato nuovamente il rendering del componente per determinare se il DOM vada aggiornato.
  • -
  • Smontaggio: Un componente sta venendo rimosso dal DOM.
  • -
- -

React offre metodi del ciclo di vita che puoi specificare per inserirti in questo processo. Offriamo dei metodi il cui nome inizia per will, chiamati immediatamente prima che qualcosa accada, o per did che sono chiamati immediatamente dopo che qualcosa è accaduto.

-

Montaggio #

-
    -
  • getInitialState(): object è invocato prima che un componente viene montato. Componenti dotati di stato dovrebbero implementare questo metodo e restituire lo stato iniziale.
  • -
  • componentWillMount() è invocato immediatamente prima che si effettui il montaggio.
  • -
  • componentDidMount() è invocato immediatamente dopo che il montaggio è avvenuto. L'inizializzazione che richiede l'esistenza di nodi DOM dovrebbe avvenire in questo metodo.
  • -
-

Aggiornamento #

-
    -
  • componentWillReceiveProps(object nextProps) è invocato quando un componente montato riceve nuove proprietà. Questo metodo dovrebbe essere utilizzato per confrontare this.props e nextProps per effettuare transizioni di stato utilizzando this.setState().
  • -
  • shouldComponentUpdate(object nextProps, object nextState): boolean è invocato quando un componente decide se i cambiamenti debbano risultare in un aggiornamento del DOM. Implementa questo metodo come un'ottimizzazione per confrontare this.props con nextProps e this.state con nextState, e restituisci false se React debba rimandare l'aggiornamento.
  • -
  • componentWillUpdate(object nextProps, object nextState) è invocato immediatamente prima che l'aggiornamento avvenga. Non puoi chiamare this.setState() al suo interno.
  • -
  • componentDidUpdate(object prevProps, object prevState) è invocato immediatamente dopo che l'aggiornamento è avvenuto.
  • -
-

Smontaggio #

-
    -
  • componentWillUnmount() è invocato immediatamente prima che un componente venga smontato e distrutto. Puoi effettuare operazioni di pulizia al suo interno.
  • -
-

Metodi Montati #

-

Componenti compositi montati supportano anche i seguenti metodi:

- -
    -
  • findDOMNode(): DOMElement può essere invocato su ciascun componente montato per ottenere un riferimento al suo nodo DOM.
  • -
  • forceUpdate() può essere invocato su ciascun componente montato quando si è certi che un aspetto interno del componente è cambiato senza usare this.setState().
  • -
-

Supporto per i Browser e Polyfill #

-

A Facebook supportiamo vecchi browser, incluso IE8. Abbiamo impiegato per un lungo tempo i polyfill per consentirci di scrivere JS con un occhio al futuro. Ciò significa che non abbiamo una quantità di hack sparsi nel nostro codice e possiamo tuttavia aspettarci che il nostro codice "semplicemente funzioni". Ad esempio, anziché usare +new Date(), possiamo scrivere Date.now(). Dal momento che la versione open source di React è la stessa che usiamo internamente, vi abbiamo applicato la stessa filosofia di scrivere JS guardando avanti.

- -

In aggiunta a questa filosofia, abbiamo anche deciso, in qualità di autori di una libreria JS, non dovremmo fornire i polyfill assieme alla nostra libreria. Se ciascuna libreria facesse ciò, con buona probabilità invieresti lo stesso polyfill diverse volte, cosa che potrebbe risultare in una rilevante quantità di codice inutilizzato. Se il tuo prodotto deve supportare vecchi browser, con buona probabilità stai già usando qualcosa come es5-shim.

-

Polyfill Richiesti per Supportare Vecchi Browser #

-

es5-shim.js tratto da es5-shim di kriskowal fornisce le seguenti API indispensabili a React:

- -
    -
  • Array.isArray
  • -
  • Array.prototype.every
  • -
  • Array.prototype.forEach
  • -
  • Array.prototype.indexOf
  • -
  • Array.prototype.map
  • -
  • Date.now
  • -
  • Function.prototype.bind
  • -
  • Object.keys
  • -
  • String.prototype.split
  • -
  • String.prototype.trim
  • -
- -

es5-sham.js, anch'esso tratto da es5-shim di kriskowal, provides the following that React needs:

- -
    -
  • Object.create
  • -
  • Object.freeze
  • -
- -

La build non minificata di React richiede le seguenti API tratte da console-polyfill di paulmillr.

- -
    -
  • console.*
  • -
- -

Quando si usano elementi HTML5 in IE8 incluso <section>, <article>, <nav>, <header> e <footer>, è inoltre necessario includere html5shiv o uno script equivalente.

-

Problemi Cross-browser #

-

Nonostante React sia molto buono ad astrarre le differenze tra browser, alcuni browser sono limitati o presentano comportamenti scorretti per i quali non abbiamo potuto trovare un rimedio.

-

Evento onScroll su IE8 #

-

Su IE8 l'evento onScroll non viene propagato, e IE8 non possiede una API per definire gestori di eventi nella fase di cattura dell'evento, con il risultato che React non ha alcun modo di reagire a questi eventi. -Al momento i gestori di questo evento vengono ignorati su IE8.

- -

Leggi la issue onScroll doesn't work in IE8 su GitHub per maggiori informazioni.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/working-with-the-browser-ja-JP.html b/docs/working-with-the-browser-ja-JP.html deleted file mode 100644 index 4ed0d2cf4a..0000000000 --- a/docs/working-with-the-browser-ja-JP.html +++ /dev/null @@ -1,615 +0,0 @@ - - - - - - - ブラウザと動くこと | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- ブラウザと動くこと -

-
- -

Reactはほとんどのケースで、DOMを直接触ることからあなたを解放するパワフルな抽象性を提供します。しかし、単純に根本的なAPIにアクセスする必要がある場合もあります。サードパーティのライブラリや現存するコードと動かす必要があるかもしれません。

-

仮想DOM #

-

ReactはDOMと直接対話を行わないため、とても速いです。Reactは速いメモリ上のDOMの表現を持っています。 render() メソッドはDOMの 記述 をリターンします。Reactはこの記述とメモリ上の表現のdiffをとることができ、ブラウザを更新する最速の方法を計算することができます。

- -

加えて、Reactはブラウザ依存があるにも関わらず、W3Cの使用に則っていると保証されているイベントオブジェクトのような、完全に合成されたイベントシステムを実行します。HTML5のイベントをIE8で使うこともできます!

- -

パフォーマンスが優れており、簡単であると思われるので、ほとんどの場合、Reactの「偽のブラウザ」を使うべきです。しかし、jQueryプラグインのようなサードパーティのライブラリと動かすかもしれません。基本的なAPIに単純にアクセスする必要がある時もあります。Reactは基本的なDOMのAPIを直接使うための脱出口を提供しています。

-

参照とfindDOMNode() #

-

ブラウザと相互に影響するために、DOMノードへの参照が必要になるでしょう。ReactはコンポーネントのDOMノードへの参照を得ることができる ReactDOM.findDOMNode(component) 関数を持っています。

- -
-

注意: -findDOMNode() はマウントされたコンポーネントの上でのみ動きます(これは、DOMに配置されたコンポーネントという意味です)。まだマウントされていない(まだ作成されていないコンポーネントの上で render()findDOMNode() を呼ぶようなものです)コンポーネントの上でこれを呼ぼうとした場合、例外がスローされます。

-
- -

Reactのコンポーネントへの参照を得るためには、現在のReactコンポーネントを得るために this を使ったり、あなたがオーナーのコンポーネントを表す参照を使ったりできます。それらは、以下のように動きます。

-
var MyComponent = React.createClass({
-  handleClick: function() {
-    // 生のDOMのAPIを使ってテキスト入力に明確にフォーカスします。
-    ReactDOM.findDOMNode(this.refs.myTextInput).focus();
-  },
-  render: function() {
-    // この参照属性はコンポーネントがマウントされた時に、
-    // this.refs のコンポーネントへの参照を追加します。
-    return (
-      <div>
-        <input type="text" ref="myTextInput" />
-        <input
-          type="button"
-          value="Focus the text input"
-          onClick={this.handleClick}
-        />
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <MyComponent />,
-  document.getElementById('example')
-);
-

参照に関しての詳細 #

-

参照に関して、詳細に学ぶためと、効率的にそれらを使う方法については、参照に関しての詳細ドキュメントを読んでください。

-

コンポーネントライフサイクル #

-

コンポーネントは以下のように、ライフサイクルの3つのパートを持っています

- -
    -
  • マウンティング: コンポーネントはDOMにインサートされます。
  • -
  • アップデーティング: DOMがアップデートする必要があるとき、コンポーネントを決定するために再度レンダリングされます。
  • -
  • * アンマウンティング: コンポーネントはDOMから削除されます。
  • -
- -

Reactは上記のプロセスになるように指定できるライフサイクルメソッドを提供します。私たちは何かが起こる直前に呼ばれる 未来の メソッドと何かが起こった直後に呼ばれる 過去の メソッドを使うことができます。

-

マウンティング #

-
    -
  • getInitialState(): object はコンポーネントがマウントされる前に実行されます。ステートフルなコンポーネントはこのメソッドをインプリメントする必要があり、最初のstateのデータをリターンする必要があります。
  • -
  • componentWillMount() はマウンティングが起きる直前に実行されます。
  • -
  • componentDidMount() はマウンティングが起きた直後に実行されます。DOMノードを必要とする初期化はここで行われるべきです。
  • -
-

アップデーティング #

-
    -
  • componentWillReceiveProps(object nextProps) はマウントされたコンポーネントが新しいpropsを受け取ったときに実行されます。このメソッドは this.setState() を使ったstateの変更を実行するために this.propsnextProps とを比較するのに使われるべきです。
  • -
  • shouldComponentUpdate(object nextProps, object nextState): boolean は何かしらの変更がDOMをアップデートしなければいけないかどうかコンポーネントが決めるときに実行されます。このメソッドを this.propsnextProps そして this.statenextState の比較の最適化のために実行してください。そして、Reactがアップデートをスキップするべきときには false を返してください。
  • -
  • componentWillUpdate(object nextProps, object nextState) はアップデーティングが発生する直前に実行されます。ここで this.setState() を呼ぶことはできません。
  • -
  • componentDidUpdate(object prevProps, object prevState) はアップデーティングが発生した直後に実行されます。
  • -
-

アンマウンティング #

-
    -
  • componentWillUnmount() はコンポーネントがアンマウントされ、削除される直前に実行されます。クリーンアップはここで行われるべきです。
  • -
-

マウントのメソッド #

-

マウントされた 複合的なコンポーネントも以下のようなメソッドをサポートします。

- -
    -
  • findDOMNode(): DOMElement はレンダリングされたDOMノードへの参照を得るために、どのマウントされたコンポーネントの上でも実行されます。
  • -
  • forceUpdate()this.setState() を使うことなくコンポーネントのstateが変更された際にさらにその詳細について知るときにどのマウントされたコンポーネントの上でも実行されます。
  • -
-

ブラウザのサポートとポリフィル #

-

Facebookでは、IE8を含む古いブラウザをサポートしています。私たちは将来に向けたJSを書くことができるように、長い間ポリフィルを使ってきました。これは、私たちのコードベースにたくさんの処理が散らばり、「ただ動くだけの」コードであることを予想することしかできないことを意味します。例えば、 +new Date() を見る代わりに、 Date.now() と記述しています。オープンソースであるReactを私たちは内部で使っているので、将来に向けたJSを使うという哲学を持ち越しています。

- -

この哲学に加えて、私たちはJSのライブラリの作者として、ライブラリの一部としてポリフィルを含めるべきではないというスタンスをとっています。全てのライブラリがこのようなことを行ったなら、死んだコードの大きな塊になりうる同じポリフィルを何度も記述しなくてもよくなるでしょう。あなたのプロダクトが古いブラウザをサポートする必要があるなら、es5-shimのようなものを使うことにチャンスがあるでしょう。

-

ポリフィルは古いブラウザをサポートする必要があります #

-

kriskowal's es5-shimes5-shim.js はReactが必要とする以下のようなものを提供します。

- -
    -
  • Array.isArray
  • -
  • Array.prototype.every
  • -
  • Array.prototype.forEach
  • -
  • Array.prototype.indexOf
  • -
  • Array.prototype.map
  • -
  • Date.now
  • -
  • Function.prototype.bind
  • -
  • Object.keys
  • -
  • String.prototype.split
  • -
  • String.prototype.trim
  • -
- -

kriskowal's es5-shimes5-sham.js もまたReactが必要とする以下のようなものを提供します。

- -
    -
  • Object.create
  • -
  • Object.freeze
  • -
- -

小さくされていないReactのビルドはpaulmillr's console-polyfillにある以下のようなものを必要とします。

- -
    -
  • console.*
  • -
- -

<section><article><nav><header><footer> を含むHTML5の要素をIE8で使うときには、html5shivか、似たようなスクリプトをインクルードする必要があります。

-

クロスブラウザの問題 #

-

Reactはブラウザ間の違いを抽象化することにおいてとても優れていますが、一時的な解決ができない、制限や独特な動作をするブラウザもあります。

-

IE8のonScrollイベント #

-

IE8では onScroll イベントは発火せず、イベントのフェーズをキャプチャするハンドラを定義するAPIを持っていません。それは、Reactがそれらのイベントを検知する方法が無いということを意味します。現状、IE8ではこのイベントは無視されています。

- -

詳細な情報については、GitHubのイシューであるonScrollがIE8で動かないを参照してください。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/working-with-the-browser-ko-KR.html b/docs/working-with-the-browser-ko-KR.html deleted file mode 100644 index d4c867ab3e..0000000000 --- a/docs/working-with-the-browser-ko-KR.html +++ /dev/null @@ -1,582 +0,0 @@ - - - - - - - 브라우저에서의 동작 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 브라우저에서의 동작 -

-
- -

React는 대부분의 경우 직접 DOM을 다루지 않아도 될만큼 강력한 추상화를 제공합니다. 하지만 서드파티 라이브러리나 기존의 코드들을 다루다 보면 간혹 기저(underlying)의 API에 접근해야 할 때도 있습니다.

-

가상의 DOM #

-

React는 DOM을 직접 다루지 않기 때문에 매우 빠릅니다. React는 메모리에(in-memory) DOM의 표상(representation)을 관리합니다. render() 메소드는 사실은 DOM의 서술를 반환하고, React는 이를 메모리에 있는 DOM의 표상과 비교해 가장 빠른 방식으로 계산해서 브라우저를 업데이트해 줍니다.

- -

게다가 React는 브라우저의 괴악함(quirks)에도 불구하고 모든 이벤트 객체가 W3C 명세를 보장하도록 통합적인 이벤트 시스템을 구현했습니다. 모든 것이 일관된 방식으로 일어나고(bubbles) 효율적으로 크로스 브라우징을 수행합니다. 심지어 IE8에서도 HTML5 이벤트를 사용할 수 있습니다!

- -

더 효율적이고 쉬우므로 대개의 경우 React의 "가짜 브라우저"를 이용해 작업을 하게 될 것입니다. 하지만 간혹 jQuery 플러그인 같은 서드파티 라이브러리를 다루다 보면 기저(underlying)의 API에 접근할 필요가 있을지도 모릅니다. React는 기저의 DOM API를 직접 다루는 회피방법을 제공합니다.

-

Refs와 findDOMNode() #

-

브라우저와 상호 작용하려면 DOM 노드에 대한 참조가 필요합니다. ref를 어떤 엘리먼트에도 붙일 수 있으며, 이를 통해 컴포넌트 지원 인스턴스를 참조 할 수 있습니다. 이는 컴포넌트에 필수 적인 기능을 호출할 때나 기저의 DOM 노드에 접근하고 싶을 때 유용합니다. refs에서 컴포넌트로 문서에서 refs를 효율적으로 사용하는 법을 포함해 더 많은 내용을 익혀보세요.

- -

-

컴포넌트 생명주기 #

-

컴포넌트의 생명주기에는 세 가지 주요 부분이 있습니다:

- -
    -
  • Mounting: 컴포넌트가 DOM에 삽입되고 있습니다.
  • -
  • Updating: 컴포넌트가 DOM의 업데이트 여부를 결정하기 위해 다시 렌더링되고 있습니다.
  • -
  • Unmounting: 컴포넌트가 DOM에서 제거되고 있습니다.
  • -
- -

React는 이 프로세스에 훅을 지정할 수 있는 생명주기 메소드를 제공합니다. 발생 직전 시점을 위한 will 메소드, 발생 직후 시점을 위한 did 메소드가 있습니다.

-

Mounting #

-
    -
  • getInitialState(): object는 컴포넌트가 마운트되기 전에 호출됩니다. 상태기반 컴포넌트는 이를 구현하고 초기 상태 데이터를 리턴합니다.
  • -
  • componentWillMount()는 마운팅되기 직전에 호출됩니다.
  • -
  • componentDidMount()는 마운팅 직후 호출됩니다. 초기화에 필요한 DOM 노드는 이곳에 있어야 합니다.
  • -
-

Updating #

-
    -
  • componentWillReceiveProps(object nextProps)는 마운트된 컴포넌트가 새로운 props을 받을 때 호출됩니다. 이 메소드는 this.propsnextProps을 비교하여 this.setState()를 사용해 상태 변환을 수행하는데 사용되야 합니다.
  • -
  • shouldComponentUpdate(object nextProps, object nextState): boolean는 컴포넌트가 어떤 변경이 DOM의 업데이트를 보증하는지 결정해야 할 때 호출됩니다. 최적화하려면, React가 업데이트를 무시해야할 때 this.propsnextProps를, this.statenextState를 비교해 false를 리턴하면 됩니다.
  • -
  • componentWillUpdate(object nextProps, object nextState)는 업데이트가 발생하기 직전에 호출됩니다. 이 시점에는 this.setState()를 호출할 수 없습니다.
  • -
  • componentDidUpdate(object prevProps, object prevState)는 업데이트가 발생한 후 즉시 호출됩니다.
  • -
-

Unmounting #

-
    -
  • componentWillUnmount()는 컴포넌트가 언마운트되어 파괴되기 직전에 호출됩니다. 정리(Cleanup)는 여기서 처리해야 합니다.
  • -
-

Mounted 메소드 #

-

마운트된 합성 컴포넌트들은 다음과 같은 메소드를 지원합니다:

- -
    -
  • component.forceUpdate()this.setState()를 사용하지 않고 변경된 컴포넌트의 상태의 변경을 적용하고 싶을 때 마운트된 컴포넌트에서 사용할 수 있습니다.
  • -
-

브라우저 지원과 Polyfill #

-

페이스북에서 우리는 IE8을 포함한 구식 브라우저를 지원합니다. 미래지향적인 JS를 작성할 수 있도록 우리는 polyfill을 오랫동안 써왔습니다. 이는 우리의 코드베이스에 구식 브라우저를 위한 코드뭉치를 흩뿌려 놓을 필요가 없으며 그럼에도 우리의 코드가 "잘 작동"할 것이라 예상할 수 있음을 의미합니다. 예를 들어, +new Date() 대신에 그냥 Date.now()를 사용할 수 있습니다. 오픈소스 React는 우리가 내부에서 사용하는것과 동일하기 때문에, 우리는 이를 통해 미래지향적인 JS를 사용하는 철학을 전달했습니다.

- -

그 철학에 더하여, 우리는 또한 JS 라이브러리의 저자로서 polyfill을 라이브러리에 포함해서 배포하지 않습니다. 만약 모든 라이브러리가 이런 짓을 하면, 같은 polyfill을 여러 번 내리게 되어 쓸모없이 크기만 차지하는 죽은 코드들을 만들 것 입니다. 당신의 제품이 구식 브라우저를 지원해야한다면, es5-shim 같은 녀석을 사용할 기회가 있었을 겁니다.

-

Polyfill은 구식 브라우저를 지원하기 위해 필요하다 #

-

kriskowal's es5-shimes5-shim.js는 React에 필요한 다음의 기능을 제공합니다:

- -
    -
  • Array.isArray
  • -
  • Array.prototype.every
  • -
  • Array.prototype.forEach
  • -
  • Array.prototype.indexOf
  • -
  • Array.prototype.map
  • -
  • Date.now
  • -
  • Function.prototype.bind
  • -
  • Object.keys
  • -
  • String.prototype.split
  • -
  • String.prototype.trim
  • -
- -

kriskowal's es5-shimes5-sham.js는, React에 필요한 다음의 기능도 제공합니다:

- -
    -
  • Object.create
  • -
  • Object.freeze
  • -
- -

압축되지 않은 React 빌드는 paulmillr의 console-polyfill에서 다음의 기능이 필요합니다.

- -
    -
  • console.*
  • -
- -

<section>, <article>, <nav>, <header>, <footer>등 HTML5 엘리먼트를 IE8에서 이용하려면 html5shiv같은 스크립트가 추가로 필요합니다.

-

크로스 브라우징 이슈 #

-

React가 브라우저별 차이점을 썩 잘 추상화하긴 했지만 일부는 한정적이거나 우리가 발견하지 못한 이상한(quirky) 동작을 보여주기도 합니다.

-

IE8에서의 onScroll 이벤트 #

-

IE8에서는 onScroll 이벤트가 일어나지(bubble) 않으며, IE8은 이벤트의 캡쳐링 단계를 위한 핸들러를 정의하는 API를 갖고 있지 않습니다. 이는 React가 이 이벤트를 이해(listen) 할 방법이 없음을 뜻합니다. 현재 이 이벤트 핸들러는 IE8에서 무시됩니다.

- -

더 많은 정보는 onScroll doesn't work in IE8 GitHub 이슈를 살펴보세요.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/working-with-the-browser-zh-CN.html b/docs/working-with-the-browser-zh-CN.html deleted file mode 100644 index 020cf341f8..0000000000 --- a/docs/working-with-the-browser-zh-CN.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - - 与浏览器协作 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- 与浏览器协作 -

-
- -

React提供了强大的抽象机制使你在大多数情况下免于直接接触DOM,但有时你仅仅只需要访问底层API,也许是为了与第三方库或者已有的代码协作。

-

虚拟 DOM #

-

React非常快速是因为它从不直接操作DOM。React维持了一个快速的内存中的DOM表示。render() 方法实际上返回一个对DOM的描述,然后React能将其与内存中的“描述”进行比较,以计算出最快速的方式更新浏览器。

- -

此外,React实现了一个完备的合成事件(synthetic event)系统,以使得所有的事件对象都被保证符合W3C细则,而不论各个浏览器的怪癖,并且所有事件跨浏览器地一致并高效的冒泡(bubbles),你甚至能在IE8里使用一些HTML5事件!

- -

大多数时间你应该和React的"伪造浏览器"呆在一起,因为它更高性能并且容易推理。然而,有时你只需要访问底层API,或许是为了与第三方库比如一个jQuery插件协作。React为你提供了安全舱口来直接使用底层API。

-

Refs 和 findDOMNode() #

-

为了与浏览器互动,你需要一个指向DOM node的引用。你可以连接一个 ref 到任何的元素,这允许你引用组件的 backing instance 。如果你需要在组件上调用命令式函数,或者想访问底层的DOM节点,它很有用。要了解更多关于 refs,包括更有效使用他们的方法,请查看我们的 关于Refs的更多内容 文档。

-

组件的生命周期 #

-

组件的生命周期有三个主要部分:

- -
    -
  • 挂载: 组件被注入DOM。
  • -
  • 更新: 组件被重新渲染来决定DOM是否应被更新。
  • -
  • 卸载: 组件从DOM中被移除。
  • -
- -

React提供生命周期方法,以便你可以指定钩挂到这个过程上。我们提供了 will 方法,该方法在某事发生前被调用,did方法,在某事发生后被调用。

-

挂载 #

-
    -
  • getInitialState(): object 在组件挂载前被调用。有状态组件(Stateful components) 应该实现此函数并返回初始state的数据。
  • -
  • componentWillMount() 在挂载发生前被立即调用。
  • -
  • componentDidMount() 在挂载发生后被立即调用。 需要DOM node的初始化应该放在这里。
  • -
-

更新 #

-
    -
  • componentWillReceiveProps(object nextProps) 当挂载的组件接收到新的props时被调用。此方法应该被用于比较this.propsnextProps以用于使用this.setState()执行状态转换。
  • -
  • shouldComponentUpdate(object nextProps, object nextState): boolean 当组件决定任何改变是否要更新到DOM时被调用。作为一个优化实现比较this.propsnextPropsthis.statenextState ,如果React应该跳过更新,返回false
  • -
  • componentWillUpdate(object nextProps, object nextState) 在更新发生前被立即调用。你不能在此调用this.setState()
  • -
  • componentDidUpdate(object prevProps, object prevState) 在更新发生后被立即调用。
  • -
-

卸载 #

-
    -
  • componentWillUnmount() 在组件被卸载和摧毁前被立即调用。清理应该放在这里。
  • -
-

已挂载的方法 #

-

Mounted 复合组件同样支持以下方法:

- -
    -
  • component.forceUpdate() 可以在任何已挂载的组件上调用,在你知道某些深处的组件状态在未使用 this.setState() 就被改变了时。
  • -
-

浏览器支持 #

-

React 支持绝大多数流行的浏览器,包括 Internet Explorer 9 及以上。

- -

(我们不支持那些不支持 ES5 methods 的更老的浏览器,但你可能发现如果你的页面包含了类似 es5-shim and es5-sham 的填充物时是可以在更老的浏览器上运行的。是否做这一步取决于你自己。)

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/docs/working-with-the-browser.html b/docs/working-with-the-browser.html deleted file mode 100644 index de5122749e..0000000000 --- a/docs/working-with-the-browser.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - - Working With the Browser | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
- Edit on GitHub -

- Working With the Browser -

-
- -

React provides powerful abstractions that free you from touching the DOM directly in most cases, but sometimes you simply need to access the underlying API, perhaps to work with a third-party library or existing code.

-

The Virtual DOM #

-

React is very fast because it never talks to the DOM directly. React maintains a fast in-memory representation of the DOM. render() methods actually return a description of the DOM, and React can compare this description with the in-memory representation to compute the fastest way to update the browser.

- -

Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and efficiently across browsers. You can even use some HTML5 events in older browsers that don't ordinarily support them!

- -

Most of the time you should stay within React's "faked browser" world since it's more performant and easier to reason about. However, sometimes you simply need to access the underlying API, perhaps to work with a third-party library like a jQuery plugin. React provides escape hatches for you to use the underlying DOM API directly.

-

Refs and findDOMNode() #

-

To interact with the browser, you'll need a reference to a DOM node. You can attach a ref to any element, which allows you to reference the backing instance of the component. This is useful if you need to invoke imperative functions on the component, or want to access the underlying DOM nodes. To learn more about refs, including ways to use them effectively, see our refs to components documentation.

-

Component Lifecycle #

-

Components have three main parts of their lifecycle:

- -
    -
  • Mounting: A component is being inserted into the DOM.
  • -
  • Updating: A component is being re-rendered to determine if the DOM should be updated.
  • -
  • Unmounting: A component is being removed from the DOM.
  • -
- -

React provides lifecycle methods that you can specify to hook into this process. We provide will methods, which are called right before something happens, and did methods which are called right after something happens.

-

Mounting #

-
    -
  • getInitialState(): object is invoked before a component is mounted. Stateful components should implement this and return the initial state data.
  • -
  • componentWillMount() is invoked immediately before mounting occurs.
  • -
  • componentDidMount() is invoked immediately after mounting occurs. Initialization that requires DOM nodes should go here.
  • -
-

Updating #

-
    -
  • componentWillReceiveProps(object nextProps) is invoked when a mounted component receives new props. This method should be used to compare this.props and nextProps to perform state transitions using this.setState().
  • -
  • shouldComponentUpdate(object nextProps, object nextState): boolean is invoked when a component decides whether any changes warrant an update to the DOM. Implement this as an optimization to compare this.props with nextProps and this.state with nextState and return false if React should skip updating.
  • -
  • componentWillUpdate(object nextProps, object nextState) is invoked immediately before updating occurs. You cannot call this.setState() here.
  • -
  • componentDidUpdate(object prevProps, object prevState) is invoked immediately after updating occurs.
  • -
-

Unmounting #

-
    -
  • componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. Cleanup should go here.
  • -
-

Mounted Methods #

-

Mounted composite components also support the following method:

- -
    -
  • component.forceUpdate() can be invoked on any mounted component when you know that some deeper aspect of the component's state has changed without using this.setState().
  • -
-

Browser Support #

-

React supports most popular browsers, including Internet Explorer 9 and above.

- -

(We don't support older browsers that don't support ES5 methods, but you may find that your apps do work in older browsers if polyfills such as es5-shim and es5-sham are included in the page. You're on your own if you choose to take this path.)

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/downloads.html b/downloads.html deleted file mode 100644 index 1664f1f490..0000000000 --- a/downloads.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - Downloads | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
-
-

Downloads

-
-

Download the starter kit to get everything you need to -get started with React. The starter kit includes React and some simple example apps.

- - -

Development vs. Production Builds #

-

We provide two versions of React: an uncompressed version for development and a minified version for production. The development version includes extra warnings about common mistakes, whereas the production version includes extra performance optimizations and strips all error messages.

- -

If you're just starting out, make sure to use the development version.

-

Individual Downloads #

React 15.3.2 (development) #

-

The uncompressed, development version of react.js and react-dom.js with inline documentation (you need both files).

-
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
-<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-

React 15.3.2 (production) #

-

The compressed, production version of react.js and react-dom.js (you need both).

-
<script src="https://unpkg.com/react@15.3.2/dist/react.min.js"></script>
-<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.min.js"></script>
-

React with Add-Ons 15.3.2 (development) #

-

The uncompressed, development version of React with optional add-ons.

-
<script src="https://unpkg.com/react@15.3.2/dist/react-with-addons.js"></script>
-<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
-

React with Add-Ons 15.3.2 (production) #

-

The compressed, production version of React with optional add-ons.

-
<script src="https://unpkg.com/react@15.3.2/dist/react-with-addons.min.js"></script>
-<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.min.js"></script>
-
-
-

Note:

- -

We're using unpkg to serve these files. This is a free service with the goal to provide a hassle-free CDN for npm package authors. React is also available on other free CDNs including cdnjs and jsDelivr. If you have concerns with relying on an external host, we always recommend that you download React and serve it from your own servers.

-
-

npm #

-

We recommend using React from npm with a bundler like browserify or webpack. You can use the react and react-dom packages. After installing it using npm install --save react react-dom, you can use:

-
var React = require('react');
-var ReactDOM = require('react-dom');
-ReactDOM.render(<App />, ...);
-
-

Each of the add-ons lives in its own package.

- -

Note: by default, React will be in development mode. To use React in production mode, set the environment variable NODE_ENV to production (using envify or webpack's DefinePlugin). A minifier that performs dead-code elimination such as UglifyJS is recommended to completely remove the extra code present in development mode.

-

Bower #

$ bower install --save react
-
- - -
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/downloads/single-file-example.html b/downloads/single-file-example.html new file mode 100644 index 0000000000..11b83bf02f --- /dev/null +++ b/downloads/single-file-example.html @@ -0,0 +1,21 @@ + + + + + Hello World + + + + + +
+ + + diff --git a/img/docs/granular-dom-updates.gif b/img/docs/granular-dom-updates.gif new file mode 100644 index 0000000000000000000000000000000000000000..1651b0daefcf94651e3ee9b1c6f5cecff03e21fe GIT binary patch literal 127160 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%0AbFu^skGQD&^Y0fu6zj-qI z4ws)k)Qqe+PSSn26n8njG5&7cI#*DogDQ44UW=hCNj{E2X4ukF>Nst>fXy2kGM9QE zFECx}qgm^^DCZ|4Ct&_Ayo9V8Z@TR*@E`h(Vnu|MtC~9Jy-r_)`1H??Zru20ewt*P znV?}>9=X7|mSEcb*(6|+{rW8%>9!;4;O5A?K|`%)Y5nwh^MF<7O*_uuByX6l)eLQ@ z2vQHlngSiI=@Q(Pn5E5*?0VHimI8jexBhh zEp#9?HqJ2FPJ@V??W%CBKN=MkY>=qN&s=0yoP&pKk9yv6u9{KrcsR-+*}HCr^YPL6 zc{p-6aa}nF^6kqd^~0_-ejIg=!ES?v+wstTbyy$~UUQihbJvUN(S5ZjtS(x3Cs5?P zz;IH)_;6F=W9VgYLsGew=9Bx!JasR=T?g^bsuJ^A?6$uo$5onjr*1vE?@1Ibi(+qj zq4=bfsUFU~&TQ4`RG1&-s39${Uq zF~`6?jr0aP=ShYrmMxhyf2m4ajVESbR+pfI(4j>kJZI*JtUk3p>+x=K5*Oo!h%6

IlfzSv)OcsnX5Isg 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ℜGm{Qgy{ZQS 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

3;u88F}HfQNq|2uK1OupV&h4(G;`mT-k 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

Fk{)^ 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�#<{TrGwEzD`Ax1^J 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⩔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 GhW`f7mv(Rf literal 0 HcmV?d00001 diff --git a/img/logo_small.png b/img/logo_small.png index eea1f6744ae2534b360b70f8682ff49f409b2a9c..a6041b64f479b31a65e60a04452ca5135632c35c 100644 GIT binary patch literal 10715 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 N002ovPDHLkV1i!oh;{$~ literal 2834 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 RnnVBq002ovPDHLkV1iCMuIm5* literal 6806 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 literal 0 HcmV?d00001 diff --git a/img/logo_small_gray_2x.png b/img/logo_small_gray_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..394d2199781c90d2558b27cd880f9bbbe525f81e GIT binary patch literal 9481 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 F{s(wPl(hf= literal 0 HcmV?d00001 diff --git a/img/tutorial/tictac-empty.png b/img/tutorial/tictac-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..fabe3f03464b14c49c48227f9feb78205f5d2ed6 GIT binary patch literal 11152 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 6320168cce..8529ceb8ac 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,14 @@ + + - A JavaScript library for building user interfaces | React - - + A JavaScript library for building user interfaces - React + + @@ -44,45 +46,48 @@

+ -
-
-
React
-
- A JavaScript library for building user interfaces -
- - -
+
+
+
React
+
+ A JavaScript library for building user interfaces
- -
+ +
+
+ + + +
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
+ +
+ +
- - - - - - - - - - - - - - - -
- - - - - -
-
-

Need help?

-
-

React is worked on full-time by Facebook's product infrastructure and Instagram's user interface engineering teams. They're often around and available for questions.

-

Stack Overflow #

-

Many members of the community use Stack Overflow to ask questions. Read through the existing questions tagged with reactjs or ask your own!

-

Discussion forum #

-

For longer-form conversations about React, we've set up a discussion forum at discuss.reactjs.org. This forum is a great place for discussion about best practices and application architecture as well as the future of React. If you have an answerable code-level question, please post it to Stack Overflow instead.

- -

In the forum there's also a category for job posts and a category for discussion of our weekly meeting notes.

-

IRC #

-

Many developers and users idle on Freenode.net's IRC network in #reactjs on freenode.

-

Twitter #

-

For the latest news about React, follow @reactjs on Twitter. In addition, you can use the #reactjs hashtag to see what others are saying or add to the conversation.

- -
- - - -
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/children-props-type-ko-KR.html b/tips/children-props-type-ko-KR.html deleted file mode 100644 index 276d4ae170..0000000000 --- a/tips/children-props-type-ko-KR.html +++ /dev/null @@ -1,528 +0,0 @@ - - - - - - - 자식 속성들의 타입 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

자식 속성들의 타입

-
-

컴포넌트의 자식들(this.props.children)은 대부분 컴포넌트의 배열로 들어갑니다:

-
var GenericWrapper = React.createClass({
-  componentDidMount: function() {
-    console.log(Array.isArray(this.props.children)); // => true
-  },
-
-  render: function() {
-    return <div />;
-  }
-});
-
-ReactDOM.render(
-  <GenericWrapper><span/><span/><span/></GenericWrapper>,
-  mountNode
-);
-
-

하지만 자식이 하나만 있는 경우, this.props.children배열 래퍼(wrapper)없이 싱글 자식 컴포넌트가 됩니다. 이렇게 함으로써 배열 할당을 줄일 수 있습니다.

-
var GenericWrapper = React.createClass({
-  componentDidMount: function() {
-    console.log(Array.isArray(this.props.children)); // => false
-
-    // 경고 : 산출된 5 값은 'hello' 스트링의 길이 입니다. 존재하지 않는 배열 래퍼의 길이인 1이 아닙니다!
-
-    console.log(this.props.children.length);
-  },
-
-  render: function() {
-    return <div />;
-  }
-});
-
-ReactDOM.render(<GenericWrapper>hello</GenericWrapper>, mountNode);
-
-

this.props.children을 쉽게 다룰 수 있도록 React.Children utilities를 제공하고 있습니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/children-props-type.html b/tips/children-props-type.html index 47bfe15d89..3304ed2001 100644 --- a/tips/children-props-type.html +++ b/tips/children-props-type.html @@ -1,528 +1,10 @@ - - - - - - Type of the Children props | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Type of the Children props

-
-

Usually, a component's children (this.props.children) is an array of components:

-
var GenericWrapper = React.createClass({
-  componentDidMount: function() {
-    console.log(Array.isArray(this.props.children)); // => true
-  },
-
-  render: function() {
-    return <div />;
-  }
-});
-
-ReactDOM.render(
-  <GenericWrapper><span/><span/><span/></GenericWrapper>,
-  mountNode
-);
-
-

However, when there is only a single child, this.props.children will be the single child component itself without the array wrapper. This saves an array allocation.

-
var GenericWrapper = React.createClass({
-  componentDidMount: function() {
-    console.log(Array.isArray(this.props.children)); // => false
-
-    // warning: yields 5 for length of the string 'hello', not 1 for the
-    // length of the non-existent array wrapper!
-    console.log(this.props.children.length);
-  },
-
-  render: function() {
-    return <div />;
-  }
-});
-
-ReactDOM.render(<GenericWrapper>hello</GenericWrapper>, mountNode);
-
-

To make this.props.children easy to deal with, we've provided the React.Children utilities.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/children-undefined-ko-KR.html b/tips/children-undefined-ko-KR.html deleted file mode 100644 index ce3d1b6a3b..0000000000 --- a/tips/children-undefined-ko-KR.html +++ /dev/null @@ -1,510 +0,0 @@ - - - - - - - 정의되지 않은 this.props.children | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

정의되지 않은 this.props.children

-
-

this.props.children을 통해 자식 컴포넌트에 접근할 수 없습니다. this.props.children은 소유자에 의해 자식이 전달되도록 지정합니다:

-
var App = React.createClass({
-  componentDidMount: function() {
-    // 이는 `span`을 참조하지 않습니다! 
-    // 마지막 줄의 `<App></App>` 사이의 정의되지 않은 자식을 참조합니다.
-    console.log(this.props.children);
-  },
-
-  render: function() {
-    return <div><span/><span/></div>;
-  }
-});
-
-ReactDOM.render(<App></App>, mountNode);
-
-

서브 컴포넌트(span)에 억세스하려면, refs를 넣으세요.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/children-undefined.html b/tips/children-undefined.html index 87ed101f38..4f4ae42e30 100644 --- a/tips/children-undefined.html +++ b/tips/children-undefined.html @@ -1,510 +1,10 @@ - - - - - - this.props.children undefined | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

this.props.children undefined

-
-

You can't access the children of your component through this.props.children. this.props.children designates the children being passed onto you by the owner:

-
var App = React.createClass({
-  componentDidMount: function() {
-    // This doesn't refer to the `span`s! It refers to the children between
-    // last line's `<App></App>`, which are undefined.
-    console.log(this.props.children);
-  },
-
-  render: function() {
-    return <div><span/><span/></div>;
-  }
-});
-
-ReactDOM.render(<App></App>, mountNode);
-
-

To access your own subcomponents (the spans), place refs on them.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/communicate-between-components-ko-KR.html b/tips/communicate-between-components-ko-KR.html deleted file mode 100644 index dc79b57a10..0000000000 --- a/tips/communicate-between-components-ko-KR.html +++ /dev/null @@ -1,521 +0,0 @@ - - - - - - - 컴포넌트간의 통신 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

컴포넌트간의 통신

-
-

부모-자식 통신을 위해서는, 간단히 props를 넘기면 됩니다.

- -

자식-부모 통신을 위해서는: -GroceryList 컴포넌트가 배열로 생성된 아이템 목록을 가지고 있다고 해봅시다. 목록의 아이템이 클릭되면 아이템의 이름이 보이길 원할 겁니다:

-
var handleClick = function(i, items) {
-  console.log('클릭한 아이템: ' + items[i]);
-}
-
-function GroceryList(props) {  
-  return (
-    <div>
-      {props.items.map(function(item, i) {
-        return (
-          <div onClick={handleClick.bind(this, i, props.items)} key={i}>{item}</div>
-        );
-      })}
-    </div>
-  );
-}
-
-ReactDOM.render(
-  <GroceryList items={['사과', '바나나', '크랜베리']} />, mountNode
-);
-
-

bind(this, arg1, arg2, ...)의 사용을 확인하세요: 간단히 handleClick에 인자를 더 넘겼습니다. 이는 React의 새로운 컨셉이 아닙니다; 그냥 JavaScript죠.

- -

부모-자식 관계가 없는 두 컴포넌트간의 통신을 위해, 별도로 전역(global) 이벤트 시스템을 사용할 수 있습니다. componentDidMount()에서 이벤트를 구독하고, componentWillUnmount()에서 해제합니다. 이벤트를 받으면 setState()를 호출합니다. Flux 패턴은 이를 정리하는 방법 중 하나입니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/communicate-between-components.html b/tips/communicate-between-components.html index a280c89099..a51d40d59d 100644 --- a/tips/communicate-between-components.html +++ b/tips/communicate-between-components.html @@ -1,521 +1,10 @@ - - - - - - Communicate Between Components | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Communicate Between Components

-
-

For parent-child communication, simply pass props.

- -

For child-parent communication: -Say your GroceryList component has a list of items generated through an array. When a list item is clicked, you want to display its name:

-
var handleClick = function(i, items) {
-  console.log('You clicked: ' + items[i]);
-}
-
-function GroceryList(props) {  
-  return (
-    <div>
-      {props.items.map(function(item, i) {
-        return (
-          <div onClick={handleClick.bind(this, i, props.items)} key={i}>{item}</div>
-        );
-      })}
-    </div>
-  );
-}
-
-ReactDOM.render(
-  <GroceryList items={['Apple', 'Banana', 'Cranberry']} />, mountNode
-);
-
-

Notice the use of bind(this, arg1, arg2, ...): we're simply passing more arguments to handleClick. This is not a new React concept; it's just JavaScript.

- -

For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event. Flux pattern is one of the possible ways to arrange this.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/componentWillReceiveProps-not-triggered-after-mounting-ko-KR.html b/tips/componentWillReceiveProps-not-triggered-after-mounting-ko-KR.html deleted file mode 100644 index 04455e1388..0000000000 --- a/tips/componentWillReceiveProps-not-triggered-after-mounting-ko-KR.html +++ /dev/null @@ -1,497 +0,0 @@ - - - - - - - 마운트 후에는 componentWillReceiveProps가 실행되지 않음. | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

마운트 후에는 componentWillReceiveProps가 실행되지 않음.

-
-

componentWillReceiveProps는 노드가 더해진 후엔 실행되지 않습니다. 이는 설계에 의한 것입니다. 다른 생명주기 메소드에서 요구사항에 적합한 것을 찾아보세요.

- -

이러한 이유는 componentWillReceiveProps에 종종 예전 props와 액션의 차이를 비교하는 로직이 들어가기 때문입니다. 마운트할 때 트리거되지 않으면, (예전 props가 없다고 해도) 메소드의 형태를 구별하는 데 도움이 됩니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/componentWillReceiveProps-not-triggered-after-mounting.html b/tips/componentWillReceiveProps-not-triggered-after-mounting.html deleted file mode 100644 index ae8e590f20..0000000000 --- a/tips/componentWillReceiveProps-not-triggered-after-mounting.html +++ /dev/null @@ -1,497 +0,0 @@ - - - - - - - componentWillReceiveProps Not Triggered After Mounting | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

componentWillReceiveProps Not Triggered After Mounting

-
-

componentWillReceiveProps isn't triggered after the node is put on scene. This is by design. Check out other lifecycle methods for the one that suits your needs.

- -

The reason for that is because componentWillReceiveProps often handles the logic of comparing with the old props and acting upon changes; not triggering it at mounting (where there are no old props) helps in defining what the method does.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/controlled-input-null-value-ko-KR.html b/tips/controlled-input-null-value-ko-KR.html deleted file mode 100644 index 5d40516b62..0000000000 --- a/tips/controlled-input-null-value-ko-KR.html +++ /dev/null @@ -1,504 +0,0 @@ - - - - - - - 제어되는 input 내의 null 값 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

제어되는 input 내의 null 값

-
-

제어되는 컴포넌트들value 속성 값을 지정하면 유저에 의해 입력값을 바꿀 수 없습니다.

- -

value가 정해져 있는데도 입력값을 변경할 수 있는 문제를 겪고 있다면 실수로 valueundefinednull로 설정한 것일 수 있습니다.

- -

아래 짧은 예제가 있습니다; 렌더링 후, 잠시 뒤에 텍스트를 고칠 수 있는 상태가 되는 것을 확인 하실 수 있습니다.

-
ReactDOM.render(<input value="hi" />, mountNode);
-
-setTimeout(function() {
-  ReactDOM.render(<input value={null} />, mountNode);
-}, 1000);
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/controlled-input-null-value.html b/tips/controlled-input-null-value.html index d03bf74d7f..61cf51283c 100644 --- a/tips/controlled-input-null-value.html +++ b/tips/controlled-input-null-value.html @@ -1,504 +1,10 @@ - - - - - - Value of null for Controlled Input | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Value of null for Controlled Input

-
-

Specifying the value prop on a controlled component prevents the user from changing the input unless you desire so.

- -

You might have run into a problem where value is specified, but the input can still be changed without consent. In this case, you might have accidentally set value to undefined or null.

- -

The snippet below shows this phenomenon; after a second, the text becomes editable.

-
ReactDOM.render(<input value="hi" />, mountNode);
-
-setTimeout(function() {
-  ReactDOM.render(<input value={null} />, mountNode);
-}, 1000);
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/dangerously-set-inner-html-ko-KR.html b/tips/dangerously-set-inner-html-ko-KR.html deleted file mode 100644 index 07c71fca6d..0000000000 --- a/tips/dangerously-set-inner-html-ko-KR.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - Dangerously Set innerHTML | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Dangerously Set innerHTML

-
-

부적절히 innerHTML를 사용하면 사이트 간 스크립팅 (XSS) 공격에 노출됩니다. 화면의 사용자 입력을 정제하다(sanitize) 오류를 내기 쉬우며, 적절하게 사용자의 입력을 정제하지 못하면 인터넷 상 웹 취약점의 원인이 됩니다.

- -

우리 설계철학은 안전을 "쉽게" 얻는 것입니다. 개발자는 그들의 의도를 명시적으로 알려야만 "안전하지 않는" 연산을 할 수 있습니다. dangerouslySetInnerHTML prop의 이름은 의도적으로 무섭게 만든 것인데, prop 값은 문자열이 아닌 객체이고 정제된 데이터를 지정하는데 쓸 수 있습니다.

- -

보안 영향을 완전히 이해했다면, 데이터에서 나쁜 부분을 완전히 제거하고 __html 키와 정제된 값을 담은 새로운 객체를 만듭시다. 여기에 JSX 문법을 쓴 예제가 있습니다.

-
function createMarkup() { return {__html: 'First &middot; Second'}; };
-<div dangerouslySetInnerHTML={createMarkup()} />
-
-

부주의하게 <div dangerouslySetInnerHTML={getUsername()} />를 쓰면 getUsername(){__html: ''} 객체 대신 순수 문자열을 반환하기 때문에 렌더링이 안되는 것이 요점입니다. {__html:...} 문장 속의 의도는 "type/taint" 같이 숙고하는 것입니다. 함수는 이 래퍼 객체를 사용하여 정제된 객체를 반환할 수 있는 데 뒤 따라오는 dangerouslySetInnerHTML에 표시할 데이터를 전달합니다. 이런 이유로 <div dangerouslySetInnerHTML={{__html: getMarkup()}} />의 형태의 코드를 작성하는 것은 추천하지 않습니다.

- -

이 기능성은 주로 DOM 문자열을 다루는 라이브러리와 협동하기 위한 목적으로 제공하며, 포함할 HTML은 잘 정제되어야 합니다. (예: XML 검증을 통과)

- -

더 완벽한 사용 예제를 보려면 대문의 최신 예제를 참조하세요.

- - -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/dangerously-set-inner-html.html b/tips/dangerously-set-inner-html.html index 5e3361a6c3..c4d43967e5 100644 --- a/tips/dangerously-set-inner-html.html +++ b/tips/dangerously-set-inner-html.html @@ -1,505 +1,10 @@ - - - - - - Dangerously Set innerHTML | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Dangerously Set innerHTML

-
-

Improper use of the innerHTML can open you up to a cross-site scripting (XSS) attack. Sanitizing user input for display is notoriously error-prone, and failure to properly sanitize is one of the leading causes of web vulnerabilities on the internet.

- -

Our design philosophy is that it should be “easy” to make things safe, and developers should explicitly state their intent when performing “unsafe” operations. The prop name dangerouslySetInnerHTML is intentionally chosen to be frightening, and the prop value (an object instead of a string) can be used to indicate sanitized data.

- -

After fully understanding the security ramifications and properly sanitizing the data, create a new object containing only the key __html and your sanitized data as the value. Here is an example using the JSX syntax:

-
function createMarkup() { return {__html: 'First &middot; Second'}; };
-<div dangerouslySetInnerHTML={createMarkup()} />
-
-

The point being that if you unintentionally do say <div dangerouslySetInnerHTML={getUsername()} /> it will not be rendered because getUsername() would return a plain string and not a {__html: ''} object. The intent behind the {__html:...} syntax is that it be considered a "type/taint" of sorts. Sanitized data can be returned from a function using this wrapper object, and this marked data can subsequently be passed into dangerouslySetInnerHTML. For this reason, we recommend against writing code of the form <div dangerouslySetInnerHTML={{__html: getMarkup()}} />.

- -

This functionality is mainly provided for cooperation with DOM string manipulation libraries, so the HTML provided must be well-formed (ie., pass XML validation).

- -

For a more complete usage example, refer to the last example on the front page.

- - -
- - ← Prev - - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/dom-event-listeners-ko-KR.html b/tips/dom-event-listeners-ko-KR.html deleted file mode 100644 index 38a7d32ce8..0000000000 --- a/tips/dom-event-listeners-ko-KR.html +++ /dev/null @@ -1,528 +0,0 @@ - - - - - - - 컴포넌트에서 DOM 이벤트 리스너 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

컴포넌트에서 DOM 이벤트 리스너

-
-
-

주의:

- -

이 글은 React에서 제공되지 않은 DOM 이벤트를 어떻게 붙이는지 설명합니다. (더 자세한 정보는 여기에서 보세요.). 이는 jQuery 같은 다른 라이브러리들을 통합할 때 좋습니다.

-
- -

윈도우 크기를 조절해봅시다.

-
var Box = React.createClass({
-  getInitialState: function() {
-    return {windowWidth: window.innerWidth};
-  },
-
-  handleResize: function(e) {
-    this.setState({windowWidth: window.innerWidth});
-  },
-
-  componentDidMount: function() {
-    window.addEventListener('resize', this.handleResize);
-  },
-
-  componentWillUnmount: function() {
-    window.removeEventListener('resize', this.handleResize);
-  },
-
-  render: function() {
-    return <div>Current window width: {this.state.windowWidth}</div>;
-  }
-});
-
-ReactDOM.render(<Box />, mountNode);
-
-

컴포넌트가 마운트 되고 DOM 표현을 가지게 되면 componentDidMount가 호출됩니다. 일반적인 DOM 이벤트를 붙이는 곳으로 여기를 종종 사용합니다.

- -

이벤트 콜백은 원래 엘리먼트 대신 React 컴포넌트에 바인드하는 걸 주의합시다. React는 오토바인드 과정에서 메서드를 현재 컴포넌트 인스턴스로 바인드합니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/dom-event-listeners.html b/tips/dom-event-listeners.html deleted file mode 100644 index 275c20e30b..0000000000 --- a/tips/dom-event-listeners.html +++ /dev/null @@ -1,528 +0,0 @@ - - - - - - - DOM Event Listeners in a Component | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

DOM Event Listeners in a Component

-
-
-

Note:

- -

This entry shows how to attach DOM events not provided by React (check here for more info). This is good for integrations with other libraries such as jQuery.

-
- -

Try to resize the window:

-
var Box = React.createClass({
-  getInitialState: function() {
-    return {windowWidth: window.innerWidth};
-  },
-
-  handleResize: function(e) {
-    this.setState({windowWidth: window.innerWidth});
-  },
-
-  componentDidMount: function() {
-    window.addEventListener('resize', this.handleResize);
-  },
-
-  componentWillUnmount: function() {
-    window.removeEventListener('resize', this.handleResize);
-  },
-
-  render: function() {
-    return <div>Current window width: {this.state.windowWidth}</div>;
-  }
-});
-
-ReactDOM.render(<Box />, mountNode);
-
-

componentDidMount is called after the component is mounted and has a DOM representation. This is often a place where you would attach generic DOM events.

- -

Notice that the event callback is bound to the react component and not the original element. React automatically binds methods to the current component instance for you through a process of autobinding.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/expose-component-functions-ko-KR.html b/tips/expose-component-functions-ko-KR.html deleted file mode 100644 index ce7f1eda93..0000000000 --- a/tips/expose-component-functions-ko-KR.html +++ /dev/null @@ -1,541 +0,0 @@ - - - - - - - 컴포넌트 함수 드러내기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

컴포넌트 함수 드러내기

-
-

컴포넌트간의 통신을 위한 (일반적이지 않은) 또다른 방법이 있습니다: 단순히 부모의 호출을 위해 자식 컴포넌트의 메소드를 노출하는 겁니다.

- -

할일 목록을 생각해보죠. 아이템을 클릭하면 제거되고, 하나가 남으면 애니메이션 효과를 줍니다:

-
var Todo = React.createClass({
-  render: function() {
-    return <div onClick={this.props.onClick}>{this.props.title}</div>;
-  },
-
-  //이 컴포넌트는 `ref` 어트리뷰트를 통해 부모에게 다뤄질 것입니다
-  animate: function() {
-    console.log('%s이 애니메이팅하는것처럼 속입니다', this.props.title);
-  }
-});
-
-var Todos = React.createClass({
-  getInitialState: function() {
-    return {items: ['사과', '바나나', '크랜베리']};
-  },
-
-  handleClick: function(index) {
-    var items = this.state.items.filter(function(item, i) {
-      return index !== i;
-    });
-    this.setState({items: items}, function() {
-      if (items.length === 1) {
-        this.refs.item0.animate();
-      }
-    }.bind(this));
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.state.items.map(function(item, i) {
-          var boundClick = this.handleClick.bind(this, i);
-          return (
-            <Todo onClick={boundClick} key={i} title={item} ref={'item' + i} />
-          );
-        }, this)}
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(<Todos />, mountNode);
-
-

다른 방법으로는, isLastUnfinishedItem prop을 todo에 넘기는 방식으로 원하는 바를 이룰수도 있습니다. componentDidUpdate에서 prop을 확인하고 스스로 애니메이션 효과를 주는겁니다; 하지만 애니메이션 제어를 위해 다른 prop들을 넘기게 되면 이는 금새 난잡해질 수 있습니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/expose-component-functions-zh-CN.html b/tips/expose-component-functions-zh-CN.html deleted file mode 100644 index b98f12340c..0000000000 --- a/tips/expose-component-functions-zh-CN.html +++ /dev/null @@ -1,541 +0,0 @@ - - - - - - - 暴露组件函数 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

暴露组件函数

-
-

这是另外一种组件通信的方法:在子组件中暴露出一个方法,可以让父组件去调。

- -

让我们看看这个todos的列表,在点击的时候就会被移除。如果只剩下最后一个未完成的待办事项,就执行animate函数:

-
var Todo = React.createClass({
-  render: function() {
-    return <div onClick={this.props.onClick}>{this.props.title}</div>;
-  },
-
-  //this component will be accessed by the parent through the `ref` attribute
-  animate: function() {
-    console.log('Pretend %s is animating', this.props.title);
-  }
-});
-
-var Todos = React.createClass({
-  getInitialState: function() {
-    return {items: ['Apple', 'Banana', 'Cranberry']};
-  },
-
-  handleClick: function(index) {
-    var items = this.state.items.filter(function(item, i) {
-      return index !== i;
-    });
-    this.setState({items: items}, function() {
-      if (items.length === 1) {
-        this.refs.item0.animate();
-      }
-    }.bind(this));
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.state.items.map(function(item, i) {
-          var boundClick = this.handleClick.bind(this, i);
-          return (
-            <Todo onClick={boundClick} key={i} title={item} ref={'item' + i} />
-          );
-        }, this)}
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(<Todos />, mountNode);
-
-

当然,你也可以通过在todo组件中的prop传递isLastUnfinishedItem,来让子组件在 componentDidUpdate中判断是否它是最后一个,来执行animate函数;但是,如果你通过不同的props值来控制的不同的动画,到最后可能会变得很混乱。

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/expose-component-functions.html b/tips/expose-component-functions.html deleted file mode 100644 index 444e707b7e..0000000000 --- a/tips/expose-component-functions.html +++ /dev/null @@ -1,541 +0,0 @@ - - - - - - - Expose Component Functions | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Expose Component Functions

-
-

There's another (uncommon) way of communicating between components: simply expose a method on the child component for the parent to call.

- -

Say a list of todos, which upon clicking get removed. If there's only one unfinished todo left, animate it:

-
var Todo = React.createClass({
-  render: function() {
-    return <div onClick={this.props.onClick}>{this.props.title}</div>;
-  },
-
-  //this component will be accessed by the parent through the `ref` attribute
-  animate: function() {
-    console.log('Pretend %s is animating', this.props.title);
-  }
-});
-
-var Todos = React.createClass({
-  getInitialState: function() {
-    return {items: ['Apple', 'Banana', 'Cranberry']};
-  },
-
-  handleClick: function(index) {
-    var items = this.state.items.filter(function(item, i) {
-      return index !== i;
-    });
-    this.setState({items: items}, function() {
-      if (items.length === 1) {
-        this.refs.item0.animate();
-      }
-    }.bind(this));
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.state.items.map(function(item, i) {
-          var boundClick = this.handleClick.bind(this, i);
-          return (
-            <Todo onClick={boundClick} key={i} title={item} ref={'item' + i} />
-          );
-        }, this)}
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(<Todos />, mountNode);
-
-

Alternatively, you could have achieved this by passing the todo an isLastUnfinishedItem prop, let it check this prop in componentDidUpdate, then animate itself; however, this quickly gets messy if you pass around different props to control animations.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/false-in-jsx-ko-KR.html b/tips/false-in-jsx-ko-KR.html deleted file mode 100644 index 9535bfa864..0000000000 --- a/tips/false-in-jsx-ko-KR.html +++ /dev/null @@ -1,506 +0,0 @@ - - - - - - - JSX에서 False | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

JSX에서 False

-
-

false 렌더링이 여러 상황에서 어떻게 다뤄지는지 봅시다.

- -

id="false"로 렌더링

-
ReactDOM.render(<div id={false} />, mountNode);
-
-

문자열 "false"를 입력값으로

-
ReactDOM.render(<input value={false} />, mountNode);
-
-

자식 없음

-
ReactDOM.render(<div>{false}</div>, mountNode);
-
-

div 자식으로 쓰인 문자열 "false"를 렌더링하지 않은 것은 더 일반적인 사용 사례를 허용하기 위함입니다. <div>{x > 1 && '하나 이상의 아이템을 가졌습니다.'}</div>

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/false-in-jsx.html b/tips/false-in-jsx.html index 542e473717..f26a3842c6 100644 --- a/tips/false-in-jsx.html +++ b/tips/false-in-jsx.html @@ -1,506 +1,10 @@ - - - - - - False in JSX | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

False in JSX

-
-

Here's how false renders in different situations:

- -

Renders as id="false":

-
ReactDOM.render(<div id={false} />, mountNode);
-
-

String "false" as input value:

-
ReactDOM.render(<input value={false} />, mountNode);
-
-

No child:

-
ReactDOM.render(<div>{false}</div>, mountNode);
-
-

The reason why this one doesn't render as the string "false" as a div child is to allow the more common use-case: <div>{x > 1 && 'You have more than one item'}</div>.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/if-else-in-JSX-ko-KR.html b/tips/if-else-in-JSX-ko-KR.html deleted file mode 100644 index 47e299c991..0000000000 --- a/tips/if-else-in-JSX-ko-KR.html +++ /dev/null @@ -1,553 +0,0 @@ - - - - - - - JSX에서 If-Else | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

JSX에서 If-Else

-
-

JSX 안에서는 if-else 구문이 작동하지 않습니다. 왜냐하면 JSX가 그저 함수 호출과 객체 생성의 편의 문법이기 때문입니다. 다음의 기본적인 예제를 살펴봅시다.

-
// 이 JSX 코드는
-ReactDOM.render(<div id="msg">Hello World!</div>, mountNode);
-
-// 다음의 JS 코드로 변환됩니다.
-ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode);
-
-

그렇기 때문에 if 구문을 넣을 수 없습니다. 다음 예제를 봅시다.

-
// 이 JSX 코드는
-<div id={if (condition) { 'msg' }}>Hello World!</div>
-
-// 다음의 JS 코드로 변환됩니다.
-React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
-
-

이는 올바른 JS가 아닙니다. 대신 삼항 연산자를 사용할 수 있습니다.

-
ReactDOM.render(<div id={condition ? 'msg' : ''}>Hello World!</div>, mountNode);
-
-

삼항 연산자가 충분하지 않다면 JSX구문 밖에서 if 문을 사용해 어떤 컴포넌트가 사용될 지 결정할 수 있습니다.

-
var loginButton;
-if (loggedIn) {
-  loginButton = <LogoutButton />;
-} else {
-  loginButton = <LoginButton />;
-}
-
-return (
-  <nav>
-    <Home />
-    {loginButton}
-  </nav>
-);
-
-

"inline"을 좀더 선호한다면, JSX 안에 즉시 평가되는 함수 표현식을 선언하세요.

-
return (
-  <section>
-    <h1>Color</h1>
-    <h3>Name</h3>
-    <p>{this.state.color || "white"}</p>
-    <h3>Hex</h3>
-    <p>
-      {(() => {
-        switch (this.state.color) {
-          case "red":   return "#FF0000";
-          case "green": return "#00FF00";
-          case "blue":  return "#0000FF";
-          default:      return "#FFFFFF";
-        }
-      })()}
-    </p>
-  </section>
-);
-
-
-

주의:

- -

위의 예제에 있는 ES6 화살표 함수this의 값을 구문적으로 바인드하기위해 사용되었습니다.

-
- -

Babel REPL로 지금 바로 사용해보세요.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/if-else-in-JSX-ru-RU.html b/tips/if-else-in-JSX-ru-RU.html deleted file mode 100644 index 4d059611ce..0000000000 --- a/tips/if-else-in-JSX-ru-RU.html +++ /dev/null @@ -1,553 +0,0 @@ - - - - - - - If-Else в JSX | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

If-Else в JSX

-
-

Некоторые конструкции, такие как if-else, нельзя использовать внутри JSX, так как JSX в результате преобразуется в вызов функции JS, как показано в примере:

-
// JSX:
-ReactDOM.render(<div id="msg">Hello World!</div>, mountNode);
-
-// Преобразованный в JS:
-ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode);
-
-

Это означает что оператор if нельзя встроить таким образом:

-
// JSX:
-<div id={if (condition) { 'msg' }}>Hello World!</div>
-
-// Преобразованный в JS:
-React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
-
-

В результате преобразования получается неверный JS код. В таких случаях используется тернарный условный оператор:

-
ReactDOM.render(<div id={condition ? 'msg' : null}>Hello World!</div>, mountNode);
-
-

Если тернарного оператора недостаточно, вы можете вынести оператор if, определяющий выбор компонентов, вне JSX:

-
var loginButton;
-if (loggedIn) {
-  loginButton = <LogoutButton />;
-} else {
-  loginButton = <LoginButton />;
-}
-
-return (
-  <nav>
-    <Home />
-    {loginButton}
-  </nav>
-);
-
-

Также вы можете обернуть код в немедленно вызываемую функцию и расположить её внутри JSX.

-
return (
-  <section>
-    <h1>Color</h1>
-    <h3>Name</h3>
-    <p>{this.state.color || "white"}</p>
-    <h3>Hex</h3>
-    <p>
-      {(() => {
-        switch (this.state.color) {
-          case "red":   return "#FF0000";
-          case "green": return "#00FF00";
-          case "blue":  return "#0000FF";
-          default:      return "#FFFFFF";
-        }
-      })()}
-    </p>
-  </section>
-);
-
-
-

Примечание:

- -

В приведенном выше примере, используется функция-стрелка из ES6 для связи со значением this.

-
- -

Вы можете попробовать этот синтаксис внутри Babel REPL.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/if-else-in-JSX.html b/tips/if-else-in-JSX.html deleted file mode 100644 index e845a9b4ee..0000000000 --- a/tips/if-else-in-JSX.html +++ /dev/null @@ -1,553 +0,0 @@ - - - - - - - If-Else in JSX | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

If-Else in JSX

-
-

if-else statements don't work inside JSX. This is because JSX is just syntactic sugar for function calls and object construction. Take this basic example:

-
// This JSX:
-ReactDOM.render(<div id="msg">Hello World!</div>, mountNode);
-
-// Is transformed to this JS:
-ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode);
-
-

This means that if statements don't fit in. Take this example:

-
// This JSX:
-<div id={if (condition) { 'msg' }}>Hello World!</div>
-
-// Is transformed to this JS:
-React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
-
-

That's not valid JS. You probably want to make use of a ternary expression:

-
ReactDOM.render(<div id={condition ? 'msg' : null}>Hello World!</div>, mountNode);
-
-

If a ternary expression isn't robust enough, you can use if statements outside of your JSX to determine which components should be used:

-
var loginButton;
-if (loggedIn) {
-  loginButton = <LogoutButton />;
-} else {
-  loginButton = <LoginButton />;
-}
-
-return (
-  <nav>
-    <Home />
-    {loginButton}
-  </nav>
-);
-
-

Or if you prefer a more "inline" aesthetic, define immediately-invoked function expressions inside your JSX:

-
return (
-  <section>
-    <h1>Color</h1>
-    <h3>Name</h3>
-    <p>{this.state.color || "white"}</p>
-    <h3>Hex</h3>
-    <p>
-      {(() => {
-        switch (this.state.color) {
-          case "red":   return "#FF0000";
-          case "green": return "#00FF00";
-          case "blue":  return "#0000FF";
-          default:      return "#FFFFFF";
-        }
-      })()}
-    </p>
-  </section>
-);
-
-
-

Note:

- -

In the example above, an ES6 arrow function is utilized to lexically bind the value of this.

-
- -

Try using it today with the Babel REPL.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/initial-ajax-ko-KR.html b/tips/initial-ajax-ko-KR.html deleted file mode 100644 index e8aa1fdcb9..0000000000 --- a/tips/initial-ajax-ko-KR.html +++ /dev/null @@ -1,533 +0,0 @@ - - - - - - - AJAX를 통해 초기 데이터 읽어오기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

AJAX를 통해 초기 데이터 읽어오기

-
-

componentDidMount에서 데이터를 가져옵니다. 응답이 올 때 데이터가 state에 저장되고 렌더링을 시작하여 UI를 갱신합니다.

- -

비동기 요청의 응답을 처리하여 state를 변경하기 전에, 컴포넌트가 여전히 마운트되었는지를 확인하기 위해 this.isMounted()를 사용합니다.

- -

이 예제는 희망하는 Github 사용자의 최근 gist를 가져옵니다.

-
var UserGist = React.createClass({
-  getInitialState: function() {
-    return {
-      username: '',
-      lastGistUrl: ''
-    };
-  },
-
-  componentDidMount: function() {
-    $.get(this.props.source, function(result) {
-      var lastGist = result[0];
-      if (this.isMounted()) {
-        this.setState({
-          username: lastGist.owner.login,
-          lastGistUrl: lastGist.html_url
-        });
-      }
-    }.bind(this));
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.state.username}'s last gist is
-        <a href={this.state.lastGistUrl}>here</a>.
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <UserGist source="https://api.github.com/users/octocat/gists" />,
-  mountNode
-);
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/initial-ajax.html b/tips/initial-ajax.html deleted file mode 100644 index 34454f140e..0000000000 --- a/tips/initial-ajax.html +++ /dev/null @@ -1,535 +0,0 @@ - - - - - - - Load Initial Data via AJAX | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Load Initial Data via AJAX

-
-

Fetch data in componentDidMount. When the response arrives, store the data in state, triggering a render to update your UI.

- -

When fetching data asynchronously, use componentWillUnmount to cancel any outstanding requests before the component is unmounted.

- -

This example fetches the desired Github user's latest gist:

-
var UserGist = React.createClass({
-  getInitialState: function() {
-    return {
-      username: '',
-      lastGistUrl: ''
-    };
-  },
-
-  componentDidMount: function() {
-    this.serverRequest = $.get(this.props.source, function (result) {
-      var lastGist = result[0];
-      this.setState({
-        username: lastGist.owner.login,
-        lastGistUrl: lastGist.html_url
-      });
-    }.bind(this));
-  },
-
-  componentWillUnmount: function() {
-    this.serverRequest.abort();
-  },
-
-  render: function() {
-    return (
-      <div>
-        {this.state.username}'s last gist is
-        <a href={this.state.lastGistUrl}>here</a>.
-      </div>
-    );
-  }
-});
-
-ReactDOM.render(
-  <UserGist source="https://api.github.com/users/octocat/gists" />,
-  mountNode
-);
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/inline-styles-ko-KR.html b/tips/inline-styles-ko-KR.html deleted file mode 100644 index 9290fbfe00..0000000000 --- a/tips/inline-styles-ko-KR.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - 인라인 스타일 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

인라인 스타일

-
-

React에서는 인라인 스타일을 문자열로 지정하지 않습니다. 대신 스타일 이름을 camelCased 형식으로 바꾼 키와 스타일의 값(주로 문자열입니다 - 자세히 알아보기)을 가진 객체로 지정됩니다.

-
var divStyle = {
-  color: 'white',
-  backgroundImage: 'url(' + imgUrl + ')',
-  WebkitTransition: 'all', // 'W'가 대문자임에 주의하세요
-  msTransition: 'all' // 'ms'는 유일한 소문자 벤더 프리픽스(vendor prefix)입니다
-};
-
-ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
-
-

스타일 키는 JS에서 DOM 노드의 프로퍼티에 접근하는 것과 일관성있도록 camelCased 형식입니다. (예를 들어 node.style.backgroundImage) ms를 제외한 벤더 프리픽스는 대문자로 시작해야 합니다. 따라서 WebkitTransition은 대문자 "W"를 사용합니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/inline-styles-ru-RU.html b/tips/inline-styles-ru-RU.html deleted file mode 100644 index b9860622c0..0000000000 --- a/tips/inline-styles-ru-RU.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - Встроенные стили | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Встроенные стили

-
-

В React, встроенные стили не указываются в виде строки. Вместо этого они определяются как объект, ключ которого является camelCase версией названия стиля, а значение которого является значением стиля, обычно строкой (подробнее об этом далее):

-
var divStyle = {
-  color: 'white',
-  backgroundImage: 'url(' + imgUrl + ')',
-  WebkitTransition: 'all', // обратите внимание на заглавную 'W'
-  msTransition: 'all' // 'ms' это единственный префикс в нижнем регистре
-};
-
-ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
-
-

Ключи стиля указываются в camelCase, в прямом соответствии с названиями свойств DOM-узлов в JS (например, node.style.backgroundImage). Префиксы отличные от ms должны начинаться с заглавной буквы. Вот почему у WebkitTransition в верхнем регистре "W".

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/inline-styles.html b/tips/inline-styles.html deleted file mode 100644 index 1293d1bd64..0000000000 --- a/tips/inline-styles.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - Inline Styles | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Inline Styles

-
-

In React, inline styles are not specified as a string. Instead they are specified with an object whose key is the camelCased version of the style name, and whose value is the style's value, usually a string (more on that later):

-
var divStyle = {
-  color: 'white',
-  backgroundImage: 'url(' + imgUrl + ')',
-  WebkitTransition: 'all', // note the capital 'W' here
-  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
-};
-
-ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
-
-

Style keys are camelCased in order to be consistent with accessing the properties on DOM nodes from JS (e.g. node.style.backgroundImage). Vendor prefixes other than ms should begin with a capital letter. This is why WebkitTransition has an uppercase "W".

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/introduction-ja-JP.html b/tips/introduction-ja-JP.html deleted file mode 100644 index 01e1aa31ae..0000000000 --- a/tips/introduction-ja-JP.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - イントロダクション | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

イントロダクション

-
-

Reactのtipsのセクションでは、あなたの質問の多くに答えられたり、はまりそうな罠に対する注意を行う適当な大きさの情報を提供します。

-

コントリビューティング #

-

Reactのリポジトリ現在のtipsの記事のスタイルに沿った形でプルリクエストを投げてください。プルリクエストを投げる前にレビューが必要な場合はfreenodeの #reactjs チャンネルdiscuss.reactjs.org フォーラムで助けを求めることができます。

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/introduction-ko-KR.html b/tips/introduction-ko-KR.html deleted file mode 100644 index be43c5ba9f..0000000000 --- a/tips/introduction-ko-KR.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - 개요 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

개요

-
-

React 팁 섹션에서는 여러 궁금증을 해결해주고 흔히 하는 실수를 피할 수 있도록 짧은 정보들을 제공합니다.

-

기여하기 #

-

현재 팁의 형식을 따르는 풀 리퀘스트를 React 저장소에 보내주세요. PR을 보내기 전에 리뷰가 필요하다면 freenode의 #reactjs 채널이나 discuss.reactjs.org 포럼에서 도움을 요청하실 수 있습니다.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/introduction-ru-RU.html b/tips/introduction-ru-RU.html deleted file mode 100644 index 0a7dbbe8e6..0000000000 --- a/tips/introduction-ru-RU.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - Введение | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Введение

-
-

Данный раздел советов по React содержит краткую информацию, которая поможет ответить на многие вопросы и предостеречь от распространенных ошибок.

-

Принятие участия #

-

Чтобы принять участие необходимо отправить pull request в репозиторий React следуя данной инструкции. Если есть решение, которое нуждается в обсуждении перед тем как сделать PR, можно обратиться за помощью на #reactjs канал на freenode или discuss.reactjs.org форум.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/introduction.html b/tips/introduction.html index 5741778924..ae479528d7 100644 --- a/tips/introduction.html +++ b/tips/introduction.html @@ -1,495 +1,10 @@ - - - - - - Introduction | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Introduction

-
-

The React tips section provides bite-sized information that can answer lots of questions you might have and warn you against common pitfalls.

-

Contributing #

-

Submit a pull request to the React repository following the current tips entries' style. If you have a recipe that needs review prior to submitting a PR you can find help in the #reactjs channel on freenode or the discuss.reactjs.org forum.

- - -
- - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tips/maximum-number-of-jsx-root-nodes-ko-KR.html b/tips/maximum-number-of-jsx-root-nodes-ko-KR.html deleted file mode 100644 index ba83c69fca..0000000000 --- a/tips/maximum-number-of-jsx-root-nodes-ko-KR.html +++ /dev/null @@ -1,497 +0,0 @@ - - - - - - - JSX 루트 노드의 최대 갯수 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

JSX 루트 노드의 최대 갯수

-
-

현재 컴포넌트의 render는 한 노드만 리턴할 수 있습니다. 만약 div 배열을 리턴하려면, div, span과 같은 다른 컴포넌트로 한 번 더 싸주어야 합니다.

- -

JSX는 일반 JS로 컴파일 함을 잊지말아야 합니다. 두개의 함수를 리턴하는 것은 문법적으로 맞지 않습니다. 이와 마찬가지로, 한 삼항 연산자 안에 한개 이상의 자식 컴포넌트를 넣으면 안됩니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/maximum-number-of-jsx-root-nodes-ru-RU.html b/tips/maximum-number-of-jsx-root-nodes-ru-RU.html deleted file mode 100644 index f07049b9e2..0000000000 --- a/tips/maximum-number-of-jsx-root-nodes-ru-RU.html +++ /dev/null @@ -1,497 +0,0 @@ - - - - - - - Максимальное количество корневых JSX-узлов | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Максимальное количество корневых JSX-узлов

-
-

Из метода render компонента пока что можно вернуть только один узел. Если нужно вернуть, например, несколько div, оберните их в div, span или любой другой компонент.

- -

Не забывайте, что JSX компилируется в обычный JS, и возвращение двух функций не имеет синтаксического смысла. Также не помещайте более одного дочернего элемента в тернарный оператор.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/maximum-number-of-jsx-root-nodes.html b/tips/maximum-number-of-jsx-root-nodes.html deleted file mode 100644 index 6b303d0b38..0000000000 --- a/tips/maximum-number-of-jsx-root-nodes.html +++ /dev/null @@ -1,497 +0,0 @@ - - - - - - - Maximum Number of JSX Root Nodes | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Maximum Number of JSX Root Nodes

-
-

Currently, in a component's render, you can only return one node; if you have, say, a list of divs to return, you must wrap your components within a div, span or any other component.

- -

Don't forget that JSX compiles into regular JS; returning two functions doesn't really make syntactic sense. Likewise, don't put more than one child in a ternary.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/props-in-getInitialState-as-anti-pattern-ko-KR.html b/tips/props-in-getInitialState-as-anti-pattern-ko-KR.html deleted file mode 100644 index 995549c67d..0000000000 --- a/tips/props-in-getInitialState-as-anti-pattern-ko-KR.html +++ /dev/null @@ -1,543 +0,0 @@ - - - - - - - getInitialState의 Props는 안티패턴 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

getInitialState의 Props는 안티패턴

-
-
-

주의 :

- -

이것은 React에만 국한된 팁이 아니고 안티패턴은 평범한 코드 속 에서도 종종 발생합니다. 이 글에서는 React로 간단하게 설명해 보겠습니다.

-
- -

부모로부터 받은 props를 이용하여 getInitialState에서 state를 생성할 때 종종 "진실의 소스", 예를 들어 진짜 데이터가 있는 곳을 중복으로 만들 때가 있습니다. 가능하던 안하던, 나중에 싱크되지 않는 확실한 값을 계산하고 또한 유지보수에도 문제를 야기합니다.

- -

나쁜 예제:

-
var MessageBox = React.createClass({
-  getInitialState: function() {
-    return {nameWithQualifier: 'Mr. ' + this.props.name};
-  },
-
-  render: function() {
-    return <div>{this.state.nameWithQualifier}</div>;
-  }
-});
-
-ReactDOM.render(<MessageBox name="Rogers"/>, mountNode);
-
-

더 나은 코드:

-
var MessageBox = React.createClass({
-  render: function() {
-    return <div>{'Mr. ' + this.props.name}</div>;
-  }
-});
-
-ReactDOM.render(<MessageBox name="Rogers"/>, mountNode);
-
-

(복잡한 로직이라, 메소드에서 계산하는 부분만 떼어 왔습니다.)

- -

하지만 여기서 싱크를 맞출 목적이 아님을 명확히 할 수 있다면, 이것은 안티 패턴이 아닙니다.

-
var Counter = React.createClass({
-  getInitialState: function() {
-    // initial로 시작하는 메소드는 내부에서 받은 어떠한 값을 초기화 할 목적이 있다는 것을 나타냅니다.
-    return {count: this.props.initialCount};
-  },
-
-  handleClick: function() {
-    this.setState({count: this.state.count + 1});
-  },
-
-  render: function() {
-    return <div onClick={this.handleClick}>{this.state.count}</div>;
-  }
-});
-
-ReactDOM.render(<Counter initialCount={7}/>, mountNode);
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/props-in-getInitialState-as-anti-pattern.html b/tips/props-in-getInitialState-as-anti-pattern.html deleted file mode 100644 index a244f5baa3..0000000000 --- a/tips/props-in-getInitialState-as-anti-pattern.html +++ /dev/null @@ -1,546 +0,0 @@ - - - - - - - Props in getInitialState Is an Anti-Pattern | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Props in getInitialState Is an Anti-Pattern

-
-
-

Note:

- -

This isn't really a React-specific tip, as such anti-patterns often occur in code in general; in this case, React simply points them out more clearly.

-
- -

Using props to generate state in getInitialState often leads to duplication of "source of truth", i.e. where the real data is. This is because getInitialState is only invoked when the component is first created.

- -

Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.

- -

Bad example:

-
var MessageBox = React.createClass({
-  getInitialState: function() {
-    return {nameWithQualifier: 'Mr. ' + this.props.name};
-  },
-
-  render: function() {
-    return <div>{this.state.nameWithQualifier}</div>;
-  }
-});
-
-ReactDOM.render(<MessageBox name="Rogers"/>, mountNode);
-
-

Better:

-
var MessageBox = React.createClass({
-  render: function() {
-    return <div>{'Mr. ' + this.props.name}</div>;
-  }
-});
-
-ReactDOM.render(<MessageBox name="Rogers"/>, mountNode);
-
-

(For more complex logic, simply isolate the computation in a method.)

- -

However, it's not an anti-pattern if you make it clear that the prop is only seed data for the component's internally-controlled state:

-
var Counter = React.createClass({
-  getInitialState: function() {
-    // naming it initialX clearly indicates that the only purpose
-    // of the passed down prop is to initialize something internally
-    return {count: this.props.initialCount};
-  },
-
-  handleClick: function() {
-    this.setState({count: this.state.count + 1});
-  },
-
-  render: function() {
-    return <div onClick={this.handleClick}>{this.state.count}</div>;
-  }
-});
-
-ReactDOM.render(<Counter initialCount={7}/>, mountNode);
-
- -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/references-to-components-ko-KR.html b/tips/references-to-components-ko-KR.html deleted file mode 100644 index a6a4bd34c6..0000000000 --- a/tips/references-to-components-ko-KR.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - 컴포넌트 참조 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

컴포넌트 참조

-
-

이 페이지는 이동되었습니다. refs

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/references-to-components.html b/tips/references-to-components.html deleted file mode 100644 index d5fa046178..0000000000 --- a/tips/references-to-components.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - References to Components | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

References to Components

-
-

This page has moved to: refs.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/self-closing-tag-ja-JP.html b/tips/self-closing-tag-ja-JP.html deleted file mode 100644 index fda0bda0ef..0000000000 --- a/tips/self-closing-tag-ja-JP.html +++ /dev/null @@ -1,501 +0,0 @@ - - - - - - - 自己終了タグ | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

自己終了タグ

-
-

JSXでは、 <MyComponent /> 単体は正しいですが、 <MyComponent> は正しくありません。 全てのタグは、自己終了の形式または対応する終了タグ( </MyComponent> )で閉じるべきです。

- -
-

注意:

- -

全てのReactコンポーネントは <div /> のように自己終了タグになり得ます。 <div></div> もまた同様です。

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/self-closing-tag-ko-KR.html b/tips/self-closing-tag-ko-KR.html deleted file mode 100644 index 828c5f10d9..0000000000 --- a/tips/self-closing-tag-ko-KR.html +++ /dev/null @@ -1,501 +0,0 @@ - - - - - - - 자기 자신을 닫는 태그 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

자기 자신을 닫는 태그

-
-

JSX에서 <MyComponent>는 유효하지 않고 <MyComponent />만 유효합니다. 모든 태그는 닫혀야 합니다. 자기 자신을 닫는 형식을 사용하거나 대응되는 닫는 태그(</MyComponent>)가 필요합니다.

- -
-

주의:

- -

모든 React 컴포넌트는 자기 자신을 닫을 수 있습니다: <div />. <div></div>와 동일합니다.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/self-closing-tag-ru-RU.html b/tips/self-closing-tag-ru-RU.html deleted file mode 100644 index b70816fcd4..0000000000 --- a/tips/self-closing-tag-ru-RU.html +++ /dev/null @@ -1,501 +0,0 @@ - - - - - - - Одиночный тег | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Одиночный тег

-
-

В JSX все теги необходимо закрывать. Это можно сделать либо в открывающем теге <MyComponent />, либо отдельным закрывающим тегом </MyComponent>.

- -
-

Примечание:

- -

Любой React компонент может быть одиночным: <div /> это то же самое, что <div></div>.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/self-closing-tag.html b/tips/self-closing-tag.html deleted file mode 100644 index 992fcf43d6..0000000000 --- a/tips/self-closing-tag.html +++ /dev/null @@ -1,501 +0,0 @@ - - - - - - - Self-Closing Tag | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Self-Closing Tag

-
-

In JSX, <MyComponent /> alone is valid while <MyComponent> isn't. All tags must be closed, either with the self-closing format or with a corresponding closing tag (</MyComponent>).

- -
-

Note:

- -

Every React component can be self-closing: <div />. <div></div> is also an equivalent.

-
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/style-props-value-px-ko-KR.html b/tips/style-props-value-px-ko-KR.html deleted file mode 100644 index 7087fa2f1f..0000000000 --- a/tips/style-props-value-px-ko-KR.html +++ /dev/null @@ -1,530 +0,0 @@ - - - - - - - 스타일 속성에서 특정 픽셀 값 넣는 간단한 방법 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

스타일 속성에서 특정 픽셀 값 넣는 간단한 방법

-
-

인라인 style prop에서 픽셀 값을 넣을때, React가 자동으로 숫자뒤에 "px"를 붙여줍니다. 다음과 같이 동작합니다:

-
var divStyle = {height: 10}; // "height:10px" 로 렌더링 됩니다.
-ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
-
-

더 자세한 이야기는 Inline Styles를 참고해 주시기 바랍니다.

- -

개발 하다보면 CSS 속성들이 단위 없이 그대로 유지되어야 할 때가 있을 겁니다. 아래의 프로퍼티들은 자동으로 "px"가 붙지 않는 속성 리스트 입니다:

- -
    -
  • animationIterationCount
  • -
  • boxFlex
  • -
  • boxFlexGroup
  • -
  • boxOrdinalGroup
  • -
  • columnCount
  • -
  • fillOpacity
  • -
  • flex
  • -
  • flexGrow
  • -
  • flexPositive
  • -
  • flexShrink
  • -
  • flexNegative
  • -
  • flexOrder
  • -
  • fontWeight
  • -
  • lineClamp
  • -
  • lineHeight
  • -
  • opacity
  • -
  • order
  • -
  • orphans
  • -
  • stopOpacity
  • -
  • strokeDashoffset
  • -
  • strokeOpacity
  • -
  • strokeWidth
  • -
  • tabSize
  • -
  • widows
  • -
  • zIndex
  • -
  • zoom
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/style-props-value-px-ru-RU.html b/tips/style-props-value-px-ru-RU.html deleted file mode 100644 index a026b4ed11..0000000000 --- a/tips/style-props-value-px-ru-RU.html +++ /dev/null @@ -1,530 +0,0 @@ - - - - - - - Краткая форма значений в пикселях для атрибута style | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Краткая форма значений в пикселях для атрибута style

-
-

React автоматически добавляет "px" для значений, которые указаны в числовом виде и находятся внутри встроенного стиля атрибута style, например:

-
var divStyle = {height: 10}; // получится "height:10px"
-ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
-
-

Подробная информация о встроенных стилях.

- -

Иногда бывает нужно указать значение без единицы измерения. Для этих свойств "px" не добавляется автоматически:

- -
    -
  • animationIterationCount
  • -
  • boxFlex
  • -
  • boxFlexGroup
  • -
  • boxOrdinalGroup
  • -
  • columnCount
  • -
  • fillOpacity
  • -
  • flex
  • -
  • flexGrow
  • -
  • flexPositive
  • -
  • flexShrink
  • -
  • flexNegative
  • -
  • flexOrder
  • -
  • fontWeight
  • -
  • lineClamp
  • -
  • lineHeight
  • -
  • opacity
  • -
  • order
  • -
  • orphans
  • -
  • stopOpacity
  • -
  • strokeDashoffset
  • -
  • strokeOpacity
  • -
  • strokeWidth
  • -
  • tabSize
  • -
  • widows
  • -
  • zIndex
  • -
  • zoom
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/style-props-value-px.html b/tips/style-props-value-px.html deleted file mode 100644 index 5f12a08b97..0000000000 --- a/tips/style-props-value-px.html +++ /dev/null @@ -1,530 +0,0 @@ - - - - - - - Shorthand for Specifying Pixel Values in style props | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Shorthand for Specifying Pixel Values in style props

-
-

When specifying a pixel value for your inline style prop, React automatically appends the string "px" for you after your number value, so this works:

-
var divStyle = {height: 10}; // rendered as "height:10px"
-ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
-
-

See Inline Styles for more info.

- -

Sometimes you do want to keep the CSS properties unitless. Here's a list of properties that won't get the automatic "px" suffix:

- -
    -
  • animationIterationCount
  • -
  • boxFlex
  • -
  • boxFlexGroup
  • -
  • boxOrdinalGroup
  • -
  • columnCount
  • -
  • fillOpacity
  • -
  • flex
  • -
  • flexGrow
  • -
  • flexPositive
  • -
  • flexShrink
  • -
  • flexNegative
  • -
  • flexOrder
  • -
  • fontWeight
  • -
  • lineClamp
  • -
  • lineHeight
  • -
  • opacity
  • -
  • order
  • -
  • orphans
  • -
  • stopOpacity
  • -
  • strokeDashoffset
  • -
  • strokeOpacity
  • -
  • strokeWidth
  • -
  • tabSize
  • -
  • widows
  • -
  • zIndex
  • -
  • zoom
  • -
- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/use-react-with-other-libraries-ko-KR.html b/tips/use-react-with-other-libraries-ko-KR.html deleted file mode 100644 index d691a90399..0000000000 --- a/tips/use-react-with-other-libraries-ko-KR.html +++ /dev/null @@ -1,521 +0,0 @@ - - - - - - - React와 다른 라이브러리를 함께 사용하기 | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

React와 다른 라이브러리를 함께 사용하기

-
-

React만으로 만들 필요는 없습니다. 컴포넌트의 생명주기 이벤트, 특히 componentDidMountcomponentDidUpdate는 다른 라이브러리들의 로직을 넣기에 좋은 장소입니다.

-
var App = React.createClass({
-  getInitialState: function() {
-    return {myModel: new myBackboneModel({items: [1, 2, 3]})};
-  },
-
-  componentDidMount: function() {
-    $(this.refs.placeholder).append($('<span />'));
-  },
-
-  componentWillUnmount: function() {
-    // 정리는 여기서 합니다
-  },
-
-  shouldComponentUpdate: function() {
-    // 이 컴포넌트를 다시는 업데이트하지 않도록 하죠.
-    return false;
-  },
-
-  render: function() {
-    return <div ref="placeholder"/>;
-  }
-});
-
-ReactDOM.render(<App />, mountNode);
-
-

이 방식으로 별도의 이벤트 리스너이벤트 스트림 같은 것들을 더할 수 있습니다.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - - diff --git a/tips/use-react-with-other-libraries.html b/tips/use-react-with-other-libraries.html index 79434091a3..f0e1729980 100644 --- a/tips/use-react-with-other-libraries.html +++ b/tips/use-react-with-other-libraries.html @@ -1,521 +1,10 @@ - - - - - - Use React with Other Libraries | React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - -
-

Use React with Other Libraries

-
-

You don't have to go full React. The component lifecycle events, especially componentDidMount and componentDidUpdate, are good places to put your other libraries' logic.

-
var App = React.createClass({
-  getInitialState: function() {
-    return {myModel: new myBackboneModel({items: [1, 2, 3]})};
-  },
-
-  componentDidMount: function() {
-    $(this.refs.placeholder).append($('<span />'));
-  },
-
-  componentWillUnmount: function() {
-    // Clean up work here.
-  },
-
-  shouldComponentUpdate: function() {
-    // Let's just never update this component again.
-    return false;
-  },
-
-  render: function() {
-    return <div ref="placeholder"/>;
-  }
-});
-
-ReactDOM.render(<App />, mountNode);
-
-

You can attach your own event listeners and even event streams this way.

- - -
- - ← Prev - - - Next → - -
-
-
- - -
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
- - - + + +Redirecting… + + +

Redirecting…

+Click here if you are not redirected. + diff --git a/tutorial/tutorial.html b/tutorial/tutorial.html new file mode 100644 index 0000000000..b1c2e72a39 --- /dev/null +++ b/tutorial/tutorial.html @@ -0,0 +1,644 @@ + + + + + + + + + Tutorial: Intro To React - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + +
+ Edit on GitHub +

+ Tutorial: Intro To React +

+
+ +

What We're Building #

+

Today, we're going to build an interactive tic-tac-toe game. We'll assume some familiarity with HTML and JavaScript but you should be able to follow along even if you haven't used them before.

+ +

If you like, you can check out the final result here: Final Result. Try playing the game. You can also click on a link in the move list to go "back in time" and see what the board looked like just after that move was made.

+

What is React? #

+

React is a declarative, efficient, and flexible JavaScript library for building user interfaces.

+ +

React has a few different kinds of components, but we'll start with React.Component subclasses:

+
class ShoppingList extends React.Component {
+  render() {
+    return (
+      <div className="shopping-list">
+        <h1>Shopping List for {this.props.name}</h1>
+        <ul>
+          <li>Instagram</li>
+          <li>WhatsApp</li>
+          <li>Oculus</li>
+        </ul>
+      </div>
+    );
+  }
+}
+
+// Example usage: <ShoppingList name="Mark" />
+
+

We'll get to the funny XML-like tags in a second. Your components tell React what you want to render – then React will efficiently update and render just the right components when your data changes.

+ +

Here, ShoppingList is a React component class, or React component type. A component takes in parameters, called props, and returns a hierarchy of views to display via the render method.

+ +

The render method return a description of what you want to render, and then React takes that description and renders it to the screen. In particular, render returns a React element, which is a lightweight description of what to render. Most React developers use a special syntax called JSX which makes it easier to write these structures. The <div /> syntax is transformed at build time to React.createElement('div'). The example above is equivalent to:

+
return React.createElement('div', {className: 'shopping-list'},
+  React.createElement('h1', ...),
+  React.createElement('ul', ...)
+);
+
+

You can put any JavaScript expression within braces inside JSX. Each React element is a real JavaScript object that you can store in a variable or pass around your program.

+ +

The ShoppingList component only renders built-in DOM components, but you can compose custom React components just as easily, by writing <ShoppingList />. Each component is encapsulated so it can operate independently, which allows you to build complex UIs out of simple components.

+

Getting Started #

+

Start with this example: Starter Code.

+ +

It contains the shell of what we're building today. We've provided the styles so you only need to worry about the JavaScript.

+ +

In particular, we have three components:

+ +
    +
  • Square
  • +
  • Board
  • +
  • Game
  • +
+ +

The Square component renders a single <div>, the Board renders 9 squares, and the Game component renders a board with some placeholders that we'll fill in later. None of the components are interactive at this point.

+ +

(The end of the JS file also defines a helper function calculateWinner that we'll use later.)

+

Passing Data Through Props #

+

Just to get our feet wet, let's try passing some data from the Board component to the Square component. In Board's renderSquare method, change the code to return <Square value={i} /> then change Square's render method to show that value by replacing {/* TODO */} with {this.props.value}.

+ +

Before:

+ +

React Devtools

+ +

After: You should see a number in each square in the rendered output.

+ +

React Devtools

+

An Interactive Component #

+

Let's make the Square component fill in an "X" when you click it. Try changing the tag returned in the render() function of the Square class to:

+
<button className="square" onClick={() => alert('click')}>
+
+

This uses the new JavaScript arrow function syntax. If you click on a square now, you should get an alert in your browser.

+ +

React components can have state by setting this.state in the constructor, which should be considered private to the component. Let's store the current value of the square in state, and change it when the square is clicked. First, add a constructor to the class to initialize the state:

+
class Square extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      value: null,
+    };
+  }
+  ...
+}
+
+

In JavaScript classes, you need to explicitly call super(); when defining the constructor of a subclass.

+ +

Now change the render method to display this.state.value instead of this.props.value, and change the event handler to be () => this.setState({value: 'X'}) instead of the alert:

+
<button className="square" onClick={() => this.setState({value: 'X'})}>
+    {this.state.value}
+</button>
+
+

Whenever this.setState is called, an update to the component is scheduled, causing React to merge in the passed state update and rerender the component along with its descendants. When the component rerenders, this.state.value will be 'X' so you'll see an X in the grid.

+ +

If you click on any square, an X should show up in it.

+

Developer Tools #

+

The React Devtools extension for Chrome and Firefox lets you inspect a React component tree in your browser devtools.

+ +

React Devtools

+ +

It lets you inspect the props and state of any of the components in your tree.

+ +

It doesn't work great on CodePen because of the multiple frames, but if you log in to CodePen and confirm your email (for spam prevention), you can go to Change View > Debug to open your code in a new tab, then the devtools will work. It's fine if you don't want to do this now, but it's good to know that it exists.

+

Lifting State Up #

+

We now have the basic building blocks for a tic-tac-toe game. But right now, the state is encapsulated in each Square component. To make a fully-working game, we now need to check if one player has won the game, and alternate placing X and O in the squares. To check if someone has won, we'll need to have the value of all 9 squares in one place, rather than split up across the Square components.

+ +

You might think that Board should just inquire what the current state of each Square is. Although it is technically possible to do this in React, it is discouraged because it tends to make code difficult to understand, more brittle, and harder to refactor.

+ +

Instead, the best solution here is to store this state in the Board component instead of in each Square – and the Board component can tell each Square what to display, like how we made each square display its index earlier.

+ +

When you want to aggregate data from multiple children or to have two child components communicate with each other, move the state upwards so that it lives in the parent component. The parent can then pass the state back down to the children via props, so that the child components are always in sync with each other and with the parent.

+ +

Pulling state upwards like this is common when refactoring React components, so let's take this opportunity to try it out. Add an initial state for Board containing an array with 9 nulls, corresponding to the 9 squares:

+
class Board extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      squares: Array(9).fill(null),
+    };
+  }
+}
+
+

We'll fill it in later so that a board looks something like

+
[
+  'O', null, 'X',
+  'X', 'X', 'O',
+  'O', null, null,
+]
+
+

Pass the value of each square down:

+
renderSquare(i) {
+  return <Square value={this.state.squares[i]} />;
+}
+
+

And change Square to use this.props.value again. Now we need to change what happens when a square is clicked. The Board component now stores which squares are filled, which means we need some way for Square to update the state of Board. Since component state is considered private, we can't update Board's state directly from Square. The usual pattern here is pass down a function from Board to Square that gets called when the square is clicked. Change renderSquare again so that it reads:

+
return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)} />;
+
+

Now we're passing down two props from Board to Square: value and onClick. The latter is a function that Square can call. So let's do that by changing render in Square to have:

+
<button className="square" onClick={() => this.props.onClick()}>
+
+

This means that when the square is clicked, it calls the onClick function that was passed by the parent. The onClick doesn't have any special meaning here, but it's popular to name handler props starting with on and their implementations with handle. Try clicking a square – you should get an error because we haven't defined handleClick yet. Add it to the Board class:

+
handleClick(i) {
+  const squares = this.state.squares.slice();
+  squares[i] = 'X';
+  this.setState({squares: squares});
+}
+
+

We call .slice() to copy the squares array instead of mutating the existing array. Jump ahead a section to learn why immutability is important.

+ +

Now you should be able to click in squares to fill them again, but the state is stored in the Board component instead of in each Square, which lets us continue building the game. Note how whenever Board's state changes, the Square components rerender automatically.

+ +

Square no longer keeps its own state; it receives its value from its parent Board and informs its parent when it's clicked. We call components like this controlled components.

+

Why Immutability Is Important #

+

In the previous code example, I suggest using the .slice() operator to copy the squares array prior to making changges and to prevent mutating the existing array. Let's talk about what this means and why it an important concept to learn.

+ +

There are generally two ways for changing data. The first, and most common method in past, has been to mutate the data by directly changing the values of a variable. The second method is to replace the data with a new copy of the object that also includes desired changes.

+

Data change with mutation #

var player = {score:  1}
+player.score = 2 // same object mutated {score: 2}
+

Data change without mutation #

var player = {score: 1}
+player = {...player, score: 2} // new object not mutated {score: 2}
+
+

The end result is the same but by not mutating (or changing the underlying data) directly we now have an added benefit that can help us increase component and overall application performance.

+

Tracking Changes #

+

Determining if a mutated object has changed is complex because changes are made directly to the object. This then requires comparing the current object to a previous copy, traversing the entire object tree, and comparing each variable and value. This process can become increasingly complex.

+ +

Determining how a immutable object has changed is considerably easier. If the object being referenced is different from before, then the object has changed. That's it.

+

Determining When To Re-render in React #

+

The biggest benefit of immutability in React comes when you build simple pure components. Since immutable data can more easily determine if changes have been made it also helps to determine when a component requires being re-rendered.

+ +

To learn how you can build pure components take a look at shouldComponentUpdate(). Also, take a look at the immutability.js library to strictly enforce immutable data.

+

Functional Components #

+

Back to our project, you can now delete the constructor from Square; we won't need it any more. In fact, React supports a simpler syntax called stateless functional components for component types like Square that only consist of a render method. Rather than define a class extending React.Component, simply write a function that takes props and returns what should be rendered:

+
function Square(props) {
+  return (
+    <button className="square" onClick={() => props.onClick()}>
+      {props.value}
+    </button>
+  );
+}
+
+

You'll need to change this.props to props both times it appears. Many components in your apps will be able to written as functional components: these components tend to be easier to write and React will optimize them more in the future.

+

Taking Turns #

+

An obvious defect in our game is that only X can play. Let's fix that.

+ +

Let's default the first move to be by 'X'. Modify our starting state in our Game constructor.

+
class Board extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      ...
+      xIsNext: true,
+    };
+  }
+
+

Each time we move we shall toggle xIsNext by flipping the boolean value and saving the state. Now update our handleClick function to flip the value of xIsNext.

+
handleClick(i) {
+  const squares = this.state.squares.slice();
+  squares[i] = this.state.xIsNext ? 'X' : 'O';
+  this.setState({
+    squares: squares,
+    xIsNext: !this.state.xIsNext,
+  });
+}
+
+

Now X and O take turns. Next, change the "status" text in Board's render so that it also displays who is next.

+

Declaring a Winner #

+

Let's show when the game is won. A calculateWinner(squares) helper function that takes the list of 9 values has been provided for you at the bottom of the file. You can call it in Board's render function to check if anyone has won the game and make the status text show "Winner: [X/O]" when someone wins:

+
render() {
+  const winner = calculateWinner(this.state.squares);
+  let status;
+  if (winner) {
+    status = 'Winner: ' + winner;
+  } else {
+    status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
+  }
+  ...
+}
+
+

You can now change handleClick to return early and ignore the click if someone has already won the game or if a square is already filled:

+
handleClick(i) {
+  const squares = this.state.squares.slice();
+  if (calculateWinner(squares) || squares[i]) {
+    return;
+  }
+  ...
+}
+
+

Congratulations! You now have a working tic-tac-toe game. And now you know the basics of React. So you're probably the real winner here.

+

Storing a History #

+

Let's make it possible to revisit old states of the board so we can see what it looked like after any of the previous moves. We're already creating a new squares array each time a move is made, which means we can easily store the past board states simultaneously.

+ +

Let's plan to store an object like this in state:

+
history = [
+  {
+    squares: [null x 9]
+  },
+  {
+    squares: [... x 9]
+  },
+  ...
+]
+
+

We'll want the top-level Game component to be responsible for displaying the list of moves. So just as we pulled the state up before from Square into Board, let's now pull it up again from Board into Game – so that we have all the information we need at the top level.

+ +

First, set up the initial state for Game:

+
class Game extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      history: [{
+        squares: Array(9).fill(null)
+      }],
+      xIsNext: true
+    };
+  }
+  ...
+}
+
+

Then remove the constructor and change Board so that it takes squares via props and has its own onClick prop specified by Game, like the transformation we made for Square and Board earlier. You can pass the location of each square into the click handler so that we still know which square was clicked:

+
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
+
+

Game's render should look at the most recent history entry and can take over calculating the game status:

+
const history = this.state.history;
+const current = history[history.length - 1];
+const winner = calculateWinner(current.squares);
+
+let status;
+if (winner) {
+  status = 'Winner: ' + winner;
+} else {
+  status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
+}
+...
+<div className="game-board">
+  <Board
+    squares={current.squares}
+    onClick={() => this.handleClick(i)}
+  />
+</div>
+<div className="game-info">
+  <div>{status}</div>
+  <ol>{/* TODO */}</ol>
+</div>
+
+

Its handleClick can push a new entry onto the stack by concatenating the new history entry to make a new history array:

+
handleClick(i) {
+  var history = this.state.history;
+  var current = history[history.length - 1];
+  const squares = current.squares.slice();
+  if (calculateWinner(squares) || squares[i]) {
+    return;
+  }
+  squares[i] = this.state.xIsNext(current.squares) ? 'X' : 'O';
+  this.setState({
+    history: history.concat([{
+      squares: squares
+    }]),
+    xIsNext: !this.state.xIsNext,
+  });
+}
+
+

At this point, Board only needs renderStep and render; the state initialization and click handler should both live in Game.

+

Showing the Moves #

+

Let's show the previous moves made in the game so far. We learned earlier that React elements are first-class JS objects and we can store them or pass them around. To render multiple items in React, we pass an array of React elements. The most common way to build that array is to map over your array of data. Let's do that in the render method of Game:

+
const moves = history.map((step, move) => {
+  const desc = move ?
+    'Move #' + move :
+    'Game start';
+  return (
+    <li key={move}>
+      <a href="#" onClick={() => this.jumpTo(move)}>{desc}</a>
+    </li>
+  );
+});
+...
+<ol>{moves}</ol>
+
+

For each step in the history, we create a list item <li> with a link <a> inside it that goes nowhere (href="#") but has a click handler which we'll implement shortly. With this code, you should see a list of the moves that have been made in the game, along with a warning that says

+ +
+

Warning: + Each child in an array or iterator should have a unique "key" prop. Check the render method of "Game".

+
+ +

Let's talk about what that warning means.

+

Keys #

+

When you render a list of items, React always stores some info about each item in the list. If you render a component that has state, that state needs to be stored – and regardless of how you implement your components, React stores a reference to the backing native views.

+ +

When you update that list, React needs to determine what has changed. You could've added, removed, rearranged, or updated items in the list.

+ +

Imagine transitioning from

+
<li>Alexa: 7 tasks left</li>
+<li>Ben: 5 tasks left</li>
+
+

to

+
<li>Ben: 9 tasks left</li>
+<li>Claudia: 8 tasks left</li>
+<li>Alexa: 5 tasks left</li>
+
+

To a human eye, it looks likely that Alexa and Ben swapped places and Claudia was added – but React is just a computer program and doesn't know what you intended it to do. As a result, React asks you to specify a key property on each element in a list, a string to differentiate each component from its siblings. In this case, alexa, ben, claudia might be sensible keys; if the items correspond to objects in a database, the database ID is usually a good choice:

+
<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>
+
+

key is a special property that's reserved by React (along with ref, a more advanced feature). When an element is created, React pulls off the key property and stores the key directly on the returned element. Even though it may look like it is part of props, it cannot be referenced with this.props.key. React uses the key automatically while deciding which children to update; there is no way for a component to inquire about its own key.

+ +

When a list is rerendered, React takes each element in the new version and looks for one with a matching key in the previous list. When a key is added to the set, a component is created; when a key is removed, a component is destroyed. Keys tell React about the identity of each component, so that it can maintain the state across rerenders. If you change the key of a component, it will be completely destroyed and recreated with a new state.

+ +

It's strongly recommended that you assign proper keys whenever you build dynamic lists. If you don't have an appropriate key handy, you may want to consider restructuring your data so that you do.

+ +

If you don't specify any key, React will warn you and fall back to using the array index as a key – which is not the correct choice if you ever reorder elements in the list or add/remove items anywhere but the bottom of the list. Explicitly passing key={i} silences the warning but has the same problem so isn't recommended in most cases.

+ +

Component keys don't need to be globally unique, only unique relative to the immediate siblings.

+

Implementing Time Travel #

+

For our move list, we already have a unique ID for each step: the number of the move when it happened. Add the key as <li key={move}> and the key warning should disappear.

+ +

Clicking any of the move links throws an error because jumpTo is undefined. Let's add a new key to Game's state to indicate which step we're currently viewing. First, add stepNumber: 0 to the initial state, then have jumpTo update that state.

+ +

We also want to update xIsNext. We set xIsNext to true if the index of the move number is an even number.

+
jumpTo(step) {
+  this.setState({
+    stepNumber: step,
+    xIsNext: (step % 2) ? false : true,
+  });
+}
+
+

Then update stepNumber when a new move is made by adding stepNumber: history.length to the state update in handleClick. Now you can modify render to read from that step in the history:

+
const current = history[this.state.stepNumber];
+
+

If you click any move link now, the board should immediately update to show what the game looked like at that time. You may also want to update handleClick to be aware of stepNumber when reading the current board state so that you can go back in time then click in the board to create a new entry. (Hint: It's easiest to .slice() off the extra elements from history at the very top of handleClick.)

+

Wrapping Up #

+

Now, you've made a tic-tac-toe game that:

+ +
    +
  • lets you play tic-tac-toe,
  • +
  • indicates when one player has won the game,
  • +
  • stores the history of moves during the game,
  • +
  • allows players to jump back in time to see older versions of the game board.
  • +
+ +

Nice work! We hope you now feel like you have a decent grasp on how React works.

+ +

If you have extra time or want to practice your new skills, here are some ideas for improvements you could make, listed in order of increasing difficulty:

+ +
    +
  1. Display the move locations in the format "(1, 3)" instead of "6".
  2. +
  3. Bold the currently-selected item in the move list.
  4. +
  5. Rewrite Board to use two loops to make the squares instead of hardcoding them.
  6. +
  7. Add a toggle button that lets you sort the moves in either ascending or descending order.
  8. +
  9. When someone wins, highlight the three squares that caused the win.
  10. +
+ + +
+ + +
+
+
+ + + + +
+ +
+ + + diff --git a/warnings/dont-call-proptypes.html b/warnings/dont-call-proptypes.html index 8f0ed91132..9304252cc8 100644 --- a/warnings/dont-call-proptypes.html +++ b/warnings/dont-call-proptypes.html @@ -1,12 +1,14 @@ + + - Don't Call PropTypes Warning | React - - + Don't Call PropTypes Warning - React + + @@ -44,29 +46,29 @@
-
@@ -144,19 +146,51 @@
-
-
- A Facebook & Instagram collaboration.
- Acknowledgements -
-
- © 2013–2016 Facebook Inc.
- Documentation licensed under CC BY 4.0. -
-
-
-
+ + + +