#reactjs
Вопрос:
Я знаю, что это хорошо известная проблема, и есть так много статей, вопросов и ответов. Но у меня все еще есть нерешенная проблема (возможно, я не смог ее найти).
Во-первых, вот код.
Контекст
import React, { FC, createContext, useContext, useState } from 'react';
// Context
const useCounterAndContent = () => {
const [count, setCount] = useState(0);
const [content, setContent] = useState('');
const increase = () => setCount(count 1);
return {
count,
increase,
content,
setContent
};
};
const CounterAndContentContext = createContext<null | ReturnType<typeof useCounterAndContent>>(null);
const CounterAndContentContextProvider: FC = ({ children }) => {
const counter = useCounterAndContent();
<CounterAndContentContext.Provider value={counter}>
{children}
</CounterAndContentContext.Provider>
};
Компоненты
// wrapper for checking re-render
const Floor: FC<{ name: string; }> = ({ children, name }) => {
console.log(`render floor of ${name}`);
return <div>{children}</div>;
};
const Counter: FC = () => {
const counterAndContent = useContext(CounterAndContentContext);
console.log('render Counter');
return (
<>
<span>{counterAndContent?.count}</span>
<button type="button" onClick={() => counterAndContent?.increase()}>
Increase
</button>
</>
);
};
const InputContent = () => {
const counterAndContent = useContext(CounterAndContentContext);
console.log('render InputContent');
return (
<input
type="text"
value={counterAndContent?.content}
onChange={({ target: { value } }) => counterAndContent?.setContent(value)}
/>
);
};
And here is the main issue.
1
const Main = () => {
return (
<CounterAndContentContextProvider>
<Floor name="counter">
<Counter />
</Floor>
</CounterAndContentContextProvider>
);
};
When I make an app like this, and click the Increase button(Counter Component) two times, the console shows
render floor of counter -> when render
render Counter -> when render
render Counter -> when click
render Counter -> when click
2
const Main = () => {
return (
<CounterAndContentContextProvider>
<Floor name="counter">
<Counter />
</Floor>
<Floor name="content">
<InputContent />
</Floor>
</CounterAndContentContextProvider>
);
};
When I make an app like this, and click the Increase button(Counter Component) two times, the console shows. It also happen whenever change the input value.
render floor of counter -> when render
render Counter -> when render
render floor of content -> when render
render InputContent -> when render
render Counter -> when click
render InputContent -> when click
render Counter -> when click
render InputContent -> when click
The Floor
component is only rendered when the App is rendered. But I think the InputContent
component and Counter
component is not related to each other, i.e. when I click the Increase button, React have to render the Counter
component only not InputContent
component.
How can I achieve it? (when I click the Increase button, the Counter
component is only rendered)
plus
I make the context CounterAndContentContext
like following
const CounterAndContentContext = createContext<null | ReturnType<typeof useCounterAndContent>>(null);
и используйте его в компоненте, например (используя необязательную цепочку)
({ target: { value } }) => counterAndContent?.setContent(value)
Есть ли какой-нибудь способ использовать это как ?
const CounterAndContentContext = createContext<ReturnType<typeof useCounterAndContent>>(proper value);
// remove optional chaining
({ target: { value } }) => counterAndContent.setContent(value)