<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [toc] [https://reactjs.org/docs/context.html](https://reactjs.org/docs/context.html) `Context API`, 提供了一種在`組件樹`中快速傳遞數據的方法。 在傳統的React應用中,數據一般是從上至下通過`props`傳遞的(\<Component prop1=xxx\>),但是這種方式如果組件嵌套很深,我們就需要一層接一層的往下傳,就會顯得非常蠢。 So,`Context API`就是為了解決這個問題孕育而生的。 ## when to Use Contex 在組件樹中,通過`Context API` 分享的數據,可以被當成“全局”變量一樣的存在。反之,我們通過`Context API`分享的數據最好具有全局性,比如一些類似和主題相關、用戶認證相關、語言偏好什么的數據。 --- 下面的代碼中我們通過手動傳遞一個`theme`屬性來使Button組件獲得其父組件傳遞給它的樣式相關數據。 ``` class App extends React.Component{ render(){ return <Toolbar theme="dark"/> } } function Toolbar(props){ return ( <div> <ThemedButton theme={props.theme}> </div> ) } function ThemedButton(props){ return <Button theme={props.theme}> } ``` 這種方式灰常麻煩,首先必須往Toolbar組件的props中添加一個`theme`,接著如果過這個組件中有很多個Button,我們還需要挨個將theme傳遞給每一個button。 接下來,我們來看`contex`是如何在組件樹中傳遞數據的 ``` //首先創建一個context,并且給一個默認值'light' const ThemeContext = React.createContext('lignt'); class App extends React.Component{ render(){ return ( //用Provider組件傳遞數據 //任何下層(不論多么深的層級)的組件皆可讀到這些數據 //現在value為dark不再為light <ThemeContext.Provider value='dark'> <Toolbar/> </ThemeContext.Provider> ) } } function Toolbar(props){ return ( <div> ` ` <ThemedButton/> </div> ) } function ThemedButton(props){ return ( //通過consumer組件來讀取theme context //react會找到離該組件最近的provider并使用其提供的value //這個栗子中 theme為dark <ThemeContext.Consumer> {theme=><Button {...props} theme={theme}/>} </ThemeContext.Consumer> ) } ``` >[warning] Context API 適用于層級比較深,同一層級有很多個組件需要接受數據的情況 ## API ### React.createContext ``` const {Provider,Consumer} = React.createContext(defaultValue); ``` `defaultValue`只會在一個`Consumer`組件在當前組件樹中匹配不到任何上級的`Provider`組件時才會生效。 這個會對沒有包裹的的獨立的測試組件有所幫助。 Note: passing undefined as a Provider value does not cause Consumers to use defaultValue. ### Provider ``` <Provider value={/* some value */}> ``` `Provider`可以**嵌套**,`Consumer`會自動獲取離其最近的Provider提供的value ### Consumer ``` <Consumer> {value => /* render something based on the context value */} </Consumer> ``` A React component that subscribes to context changes. 所有的`Consumers`在`Provider`提供的value發生改變時都會重新渲染。 Changes are determined by comparing the new and old values using the same algorithm as [Object.is](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description). (This can cause some issues when passing objects as value: see [Caveats](https://reactjs.org/docs/context.html#caveats).) >Note > >For more information about this pattern, see [render props](https://reactjs.org/docs/render-props.html). ## Examples ``` export const themes = { light: { foreground: '#000000', background: '#eeeeee', }, dark: { foreground: '#ffffff', background: '#222222', }, }; export const ThemeContext = React.createContext( themes.dark // default value ); ``` ``` import {ThemeContext} from './theme-context'; function ThemedButton(props) { return ( <ThemeContext.Consumer> {theme => ( <button {...props} style={{backgroundColor: theme.background}} /> )} </ThemeContext.Consumer> ); } export default ThemedButton; ``` ``` import {ThemeContext, themes} from './theme-context'; import ThemedButton from './themed-button'; // An intermediate component that uses the ThemedButton function Toolbar(props) { return ( <ThemedButton onClick={props.changeTheme}> Change Theme </ThemedButton> ); } class App extends React.Component { constructor(props) { super(props); this.state = { theme: themes.light, }; this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === themes.dark ? themes.light : themes.dark, })); }; } render() { // The ThemedButton button inside the ThemeProvider // uses the theme from state while the one outside uses // the default dark theme return ( <Page> <ThemeContext.Provider value={this.state.theme}> <Toolbar changeTheme={this.toggleTheme} /> </ThemeContext.Provider> <Section> <ThemedButton /> </Section> </Page> ); } } ReactDOM.render(<App />, document.root); ``` ### Updating Context from a Nested Component >theme-context.js > ``` // Make sure the shape of the default value passed to // createContext matches the shape that the consumers expect! export const ThemeContext = React.createContext({ theme: themes.dark, toggleTheme: () => {}, }); ``` `defaultValue`傳遞了一個對象,這對象包含一個`toggleTheme`方法 >theme-toggler-button.js > ``` import {ThemeContext} from './theme-context'; function ThemeTogglerButton() { // The Theme Toggler Button receives not only the theme // but also a toggleTheme function from the context return ( <ThemeContext.Consumer> {({theme, toggleTheme}) => ( <button onClick={toggleTheme} style={{backgroundColor: theme.background}}> Toggle Theme </button> )} </ThemeContext.Consumer> ); } export default ThemeTogglerButton; ``` 注意:在createContext中默認的value就決定了consumer中能拿到哪些東東,也就是說這個默認的value不僅是個默認值還決定了在組件樹中那些東東能夠傳遞 >app.js > ``` import {ThemeContext, themes} from './theme-context'; import ThemeTogglerButton from './theme-toggler-button'; class App extends React.Component { constructor(props) { super(props); this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === themes.dark ? themes.light : themes.dark, })); }; // State also contains the updater function so it will // be passed down into the context provider this.state = { theme: themes.light, toggleTheme: this.toggleTheme, }; } render() { // The entire state is passed to the provider return ( <ThemeContext.Provider value={this.state}> <Content /> </ThemeContext.Provider> ); } } function Content() { return ( <div> <ThemeTogglerButton /> </div> ); } ReactDOM.render(<App />, document.root); ``` ### Consuming Multiple Contexts To keep context re-rendering fast, React needs to make each context consumer a separate node in the tree. ``` // Theme context, default to light theme const ThemeContext = React.createContext('light'); // Signed-in user context const UserContext = React.createContext({ name: 'Guest', }); class App extends React.Component { render() { const {signedInUser, theme} = this.props; // App component that provides initial context values return ( <ThemeContext.Provider value={theme}> <UserContext.Provider value={signedInUser}> <Layout /> </UserContext.Provider> </ThemeContext.Provider> ); } } function Layout() { return ( <div> <Sidebar /> <Content /> </div> ); } // A component may consume multiple contexts function Content() { return ( <ThemeContext.Consumer> {theme => ( <UserContext.Consumer> {user => ( <ProfilePage user={user} theme={theme} /> )} </UserContext.Consumer> )} </ThemeContext.Consumer> ); } ``` If two or more context values are often used together, you might want to consider creating your own render prop component that provides both. ### Accessing Context in Lifecycle Methods Accessing values from context in lifecycle methods is a relatively common use case. Instead of adding context to every lifecycle method, you just need to pass it as a prop, and then work with it just like you’d normally work with a prop. ``` class Button extends React.Component { componentDidMount() { // ThemeContext value is this.props.theme } componentDidUpdate(prevProps, prevState) { // Previous ThemeContext value is prevProps.theme // New ThemeContext value is this.props.theme } render() { const {theme, children} = this.props; return ( <button className={theme ? 'dark' : 'light'}> {children} </button> ); } } export default props => ( <ThemeContext.Consumer> {theme => <Button {...props} theme={theme} />} </ThemeContext.Consumer> ); ``` ### Consuming Context with a HOC(高階組件) Some types of contexts are consumed by many components (e.g. theme or localization). It can be tedious to explicitly wrap each dependency with a <Context.Consumer> element. A higher-order component can help with this. For example, a button component might consume a theme context like so: ``` const ThemeContext = React.createContext('light'); function ThemedButton(props) { return ( <ThemeContext.Consumer> {theme => <button className={theme} {...props} />} </ThemeContext.Consumer> ); } ``` That’s alright for a few components, but what if we wanted to use the theme context in a lot of places? We could create a higher-order component called withTheme: ``` const ThemeContext = React.createContext('light'); // This function takes a component... export function withTheme(Component) { // ...and returns another component... return function ThemedComponent(props) { // ... and renders the wrapped component with the context theme! // Notice that we pass through any additional props as well return ( <ThemeContext.Consumer> {theme => <Component {...props} theme={theme} />} </ThemeContext.Consumer> ); }; } ``` Now any component that depends on the theme context can easily subscribe to it using the withTheme function we’ve created: ``` function Button({theme, ...rest}) { return <button className={theme} {...rest} />; } const ThemedButton = withTheme(Button); ``` ### Forwarding Refs to Context Consumers One issue with the render prop API is that refs don’t automatically get passed to wrapped elements. To get around this, use React.forwardRef: >fancy-button.js > ``` class FancyButton extends React.Component { focus() { // ... } // ... } // Use context to pass the current "theme" to FancyButton. // Use forwardRef to pass refs to FancyButton as well. export default React.forwardRef((props, ref) => ( <ThemeContext.Consumer> {theme => ( <FancyButton {...props} theme={theme} ref={ref} /> )} </ThemeContext.Consumer> )); ``` >app.js > ``` import FancyButton from './fancy-button'; const ref = React.createRef(); // Our ref will point to the FancyButton component, // And not the ThemeContext.Consumer that wraps it. // This means we can call FancyButton methods like ref.current.focus() <FancyButton ref={ref} onClick={handleClick}> Click me! </FancyButton>; ``` ## Caveats Because context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider’s parent re-renders. For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for value: ``` class App extends React.Component { render() { return ( <Provider value={{something: 'something'}}> <Toolbar /> </Provider> ); } } ``` To get around this, lift the value into the parent’s state: ``` class App extends React.Component { constructor(props) { super(props); this.state = { value: {something: 'something'}, }; } render() { return ( <Provider value={this.state.value}> <Toolbar /> </Provider> ); } } ``` >Note React previously shipped with an experimental context API. The old API will be supported in all 16.x releases, but applications using it should migrate to the new version. The legacy API will be removed in a future major React version. Read the legacy context docs here.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看