使用上下文不重新呈现子应用程序

时间:2019-04-10 14:31:50

标签: reactjs typescript react-context

我使用带有TypeScript的CRA 2.0创建了一个项目。我正在尝试使用上下文。

我的最终目标是创建一个通用数据存储,其中几乎没有可用的项目。我正在使用打字稿。

请参阅下面的代码,我的问题是,我在父级中有一个状态,我将其设置为状态并传递给它。当我在父级(带有上下文提供程序的一个)中设置状态时,它不会重新渲染子级组件,因此,即使在获取新数据后,除非重新渲染子级组件,上下文值在子级内部仍保持不变。

Interface File (`interfaces/lookups.tsx`)

interface LookupItemInterface {
  value?: number;
  text?: string;
}

export interface LookupInterface {
  assessmentTypesLookUp: LookupItemInterface[];
  billingPlansLookUp: LookupItemInterface[];
  categoriesLookUp: LookupItemInterface[];
  competenciesLookUp: LookupItemInterface[];
  emailTypesLookUp: LookupItemInterface[];
  entitiesLookUp: LookupItemInterface[];
  evaluationRolesLookUp: LookupItemInterface[];
  questionTypesLookUp: LookupItemInterface[];
  recommendedApplicationsLookUp: LookupItemInterface[];
  statesLookUp: LookupItemInterface[];
  testTypesLookUp: LookupItemInterface[];
  userRolesLookUp: LookupItemInterface[];
}

export const lookupInitialState: LookupInterface = {
  assessmentTypesLookUp: [],
  billingPlansLookUp: [],
  categoriesLookUp: [],
  competenciesLookUp: [],
  emailTypesLookUp: [],
  entitiesLookUp: [],
  evaluationRolesLookUp: [],
  questionTypesLookUp: [],
  recommendedApplicationsLookUp: [],
  statesLookUp: [],
  testTypesLookUp: [],
  userRolesLookUp: [],
};

export interface LookupContextInterface {
  findByValue?: (id: number, key: string) => void;
  lookups?: LookupInterface;
}

export const LookupContextInitialState = {
  findByValue: (id: number, key: string) => {},
  lookups: lookupInitialState,
};

这是我的上下文文件( LookupContext.tsx

import { LookupContextInitialState, LookupContextInterface } from '../interfaces/Lookup';

export const LookupContext = React.createContext<LookupContextInterface>(LookupContextInitialState);

export const LookupContextProvider = LookupContext.Provider;
export const LookupContextConsumer = LookupContext.Consumer;

export default LookupContext;

我创建了一个包装模板的容器。

const LookupContainer: React.FunctionComponent = ({ children }) => {
  const [lookupState, setLookupState] = useState({ lookups: lookupInitialState, loading: true });

  const errorContext = useContext(ErrorContext);

  useEffect(() => {
    fetchLookups();
  }, []);

  const findByValue = (id: number, key: string) => {
    console.log('find', id, key, lookupInitialState);
  };

  const fetchLookups = async () => {
    try {
      const newLookups = await getLookups();
      setLookupState({ ...lookupState, lookups: newLookups, loading: false });
    } catch (e) {
      setLookupState({ ...lookupState, loading: false });
      errorContext.setError(e, true);
    }
  };

  if (lookupState.loading) {
    return <Spinner />;
  }

  return <LookupContextProvider value={{ findByValue, lookups: lookupState.lookups }}>{children}</LookupContextProvider>;
};

我正在使用原子设计模态,现在将其包装在模板上。

const DashboardTemplate: React.FunctionComponent<Props> = ({ children }) => (
  <LookupContainer>
    <Sidebar />
    <Page>
      <TopBar />
      {children}
      <Footer />
    </Page>
  </LookupContainer>
);

最后,孩子们在下面放了一个容器

const TemplateContainer: React.FunctionComponent = ({ id }) => {
  const lookupContext = useContext(LookupContext);
  const {lookups, findById} = lookupContext; // <--- this will have initial context value unless I set state inside this and somehow re-render this

  const assessmentTypesLookUp = findById(id, 'assessmentTypesLookUp');
  return (
    <DashboardTemplate>This is Instrument</DashboardTemplate>
  );
}

0 个答案:

没有答案