업데이트되지 맥락 반응

쿠로 네코 :

내가 사용 컨텍스트는 페이지 제목을 저장하는 것을 기본 샘플 프로젝트를 설정,하지만 난 그것을 설정할 때 구성 요소가 다시 렌더링되지 않습니다.

주요 파일 :

Context.js

import React from 'react'

const Context = React.createContext({})

export default Context

AppWrapper.js

import React from 'react'
import App from './App'
import Context from './Context'

function AppWrapper () {
  return (
    <Context.Provider value={{page: {}}}>
      <App />
    </Context.Provider>
  )
}

export default AppWrapper

App.js

import React, { useContext } from 'react';
import Context from './Context';
import Home from './Home';

function App() {
  const { page } = useContext(Context)
  return (
    <>
      <h1>Title: {page.title}</h1>
      <Home />
    </>
  );
}

export default App;

Home.js

import React, { useContext } from 'react'
import Context from './Context'

function Home () {
  const { page } = useContext(Context)
  page.title = 'Home'

  return (
    <p>Hello, World!</p>
  )
}

export default Home

전체 코드

내가 도대체 ​​뭘 잘못하고있는 겁니까?

존 러델 :

에 대한 당신처럼 상황에 맞는 반응 생각 구성 요소, 당신이 값을 업데이트 할 당신이 사용할 필요가 다음을 보여 주면 state. 당신이있어이 경우 AppWrapper당신이 상태를 추적 할 필요가 어디 상황에 맞는 업체를 렌더링입니다.

import React, {useContext, useState, useCallback, useEffect} from 'react'

const PageContext = React.createContext({})

function Home() {
  const {setPageContext, page} = useContext(PageContext)
  // essentially a componentDidMount
  useEffect(() => {
    if (page.title !== 'Home')
      setPageContext({title: 'Home'})
  }, [setPageContext])
  return <p>Hello, World!</p>
}

function App() {
  const {page} = useContext(PageContext)
  return (
    <>
      <h1>Title: {page.title}</h1>
      <Home />
    </>
  )
}

function AppWrapper() {
  const [state, setState] = useState({page: {}})
  const setPageContext = useCallback(
    newState => {
      setState({page: {...state.page, ...newState}})
    },
    [state, setState],
  )
  const getContextValue = useCallback(
    () => ({setPageContext, ...state}),
    [state, updateState],
  )
  return (
    <PageContext.Provider value={getContextValue()}>
      <App />
    </PageContext.Provider>
  )
}

편집 - 연결 저장소에서 업데이트 작업 솔루션

나는 그 혼란과 구성 요소의 로컬 상태와 충돌 할 수있는 상황을 통해 setState를 통과 권하고 싶지 않다, 조금 더 구체적으로 몇 가지 이름. 또한 내가 대답에 필요하지 않은 코드의 덩어리를 생략하고있어, 단지 부분은 내가 변경

SRC / AppContext.js

export const updatePageContext = (values = {}) => ({ page: values })
export const updateProductsContext = (values = {}) => ({ products: values })

export const Pages = {
  help: 'Help',
  home: 'Home',
  productsList: 'Products list',
  shoppingCart: 'Cart',
}

const AppContext = React.createContext({})

export default AppContext

SRC / AppWrapper.js

const getDefaultState = () => {
  // TODO rehydrate from persistent storage (localStorage.getItem(myLastSavedStateKey)) ?
  return {
    page: { title: 'Home' },
    products: {},
  }
}

function AppWrapper() {
  const [state, setState] = useState(getDefaultState())

  // here we only re-create setContext when its dependencies change ([state, setState])
  const setContext = useCallback(
    updates => {
      setState({ ...state, ...updates })
    },
    [state, setState],
  )

  // here context value is just returning an object, but only re-creating the object when its dependencies change ([state, setContext])
  const getContextValue = useCallback(
    () => ({
      ...state,
      setContext,
    }),
    [state, setContext],
  )
  return (
    <Context.Provider value={getContextValue()}>
      ...

SRC / App.js

...
import AppContext, { updateProductsContext } from './AppContext'

function App() {
  const [openDrawer, setOpenDrawer] = useState(false)
  const classes = useStyles()
  const {
    page: { title },
    setContext,
  } = useContext(Context)

  useEffect(() => {
    fetch(...)
      .then(...)
      .then(items => {
        setContext(updateProductsContext({ items }))
      })
  }, [])

SRC / 구성 요소 / DocumentMeta.js

이것은 당신이 각 뷰의 코드 복잡성 / 중복을 감소 선언 스타일로 페이지의 이름을 업데이트하는 데 사용할 수있는 새로운 구성 요소입니다

import React, { useContext, useEffect } from 'react'
import Context, { updatePageContext } from '../Context'

export default function DocumentMeta({ title }) {
  const { page, setContext } = useContext(Context)

  useEffect(() => {
    if (page.title !== title) {
      // TODO use this todo as a marker to also update the actual document title so the browser tab name changes to reflect the current view
      setContext(updatePageContext({ title }))
    }
  }, [title, page, setContext])
  return null
}

일명 사용은 같은 것 <DocumentMeta title="Whatever Title I Want Here" />


SRC / 페이지 / Home.js

각 뷰는 이제 단지 DocumentMeta와 페이지 "열거는"대신 컨텍스트를 당겨 수동으로 매번 수행의 제목을 업데이트 할 가져올 필요가있다.

import { Pages } from '../Context'
import DocumentMeta from '../components/DocumentMeta'

function Home() {
  return (
    <>
      <DocumentMeta title={Pages.home} />
      <h1>WIP</h1>
    </>
  )
}

참고 : 다른 페이지는 홈 페이지가 무엇을하고 있는지 복제 할 필요가

이, 나는 성능면에서 더 많은 일을 할 수 캐시에 쓰기 데이터, 깊은 병합에 더 일반적인 도우미를 써서 .. 등을하지 내가 프로덕션 환경에서이 작업을 수행 할 어떻게 기억하지만이 있어야한다 포인트를 시작하는 좋은.

추천

출처http://43.154.161.224:23101/article/api/json?id=347029&siteId=1