我搜索了一个答案,但找不到答案,所以我在这里问, 我有一个可以更新上下文的使用者, 另一个应该显示上下文的使用者。 我正在使用带有typescript(16.3)的react
上下文(AppContext.tsx):
export interface AppContext {
jsonTransactions: WithdrawTransactionsElement | null;
setJsonTran(jsonTransactions: WithdrawTransactionsElement | null): void;
}
export const appContextInitialState : AppContext = {
jsonTransactions: null,
setJsonTran : (data: WithdrawTransactionsElement) => {
return appContextInitialState.jsonTransactions = data;
}
};
export const AppContext = React.createContext(appContextInitialState);
生产者(App.tsx):
interface Props {}
class App extends React.Component<Props, AppContext> {
state: AppContext = appContextInitialState;
constructor(props : Props) {
super(props);
}
render() {
return (
<AppContext.Provider value={this.state}>
<div className="App">
<header className="App-header">
<SubmitTransactionFile/>
<WithdrawTransactionsTable />
</header>
</div>
</AppContext.Provider>
);
}
}
export default App;
正在更新的上下文使用者(SubmitTransactionFile.tsx)
class SubmitTransactionFile extends React.Component {
private fileLoadedEvent(file: React.ChangeEvent<HTMLInputElement>, context: AppContext): void{
let files = file.target.files;
let reader = new FileReader();
if (files && files[0]) {
reader.readAsText(files[0]);
reader.onload = (json) => {
if (json && json.target) {
// @ts-ignore -> this is because result field is not recognized by typescript compiler
context.setJsonTran(JSON.parse(json.target.result))
}
}
}
}
render() {
return (
<AppContext.Consumer>
{ context =>
<div className="SubmitTransactionFile">
<label>Select Transaction File</label><br />
<input type="file" id="file" onChange={(file) =>
this.fileLoadedEvent(file, context)} />
<p>{context.jsonTransactions}</p>
</div>
}
</AppContext.Consumer>
)
}
}
export default SubmitTransactionFile;
最后确定展示消费者(WithdrawTransactionsTable.tsx):
class WithdrawTransactionsTable extends React.Component {
render() {
return (
<AppContext.Consumer>
{ context =>
<div>
<label>{context.jsonTransactions}</label>
</div>
}
</AppContext.Consumer>
)
}
}
export default WithdrawTransactionsTable;
据我了解,在调用fileLoadedEvent
函数之后,context.setJsonTran
应该重新呈现其他使用者,而WithdrawTransactionsTable
组件应该重新呈现,但不是。
我在做什么错了?
答案 0 :(得分:2)
更新状态时,不会触发提供程序的重新呈现,因此使用者数据不会更改。您应该使用setState更新状态,并将上下文值分配给提供程序,例如
class App extends React.Component<Props, AppContext> {
constructor(props : Props) {
super(props);
this.state = {
jsonTransactions: null,
setJsonTran: this.setJsonTran
};
}
setJsonTran : (data: WithdrawTransactionsElement) => {
this.setState({
jsonTransactions: data
});
}
render() {
return (
<AppContext.Provider value={this.state}>
<div className="App">
<header className="App-header">
<SubmitTransactionFile/>
<WithdrawTransactionsTable />
</header>
</div>
</AppContext.Provider>
);
}
}
export default App;
答案 1 :(得分:1)
您的setJsonTran
仅更改了上下文的默认值,而不会导致赋予value
的{{1}}发生更改。
您可以将Provider
保持在最高状态,并传递一个将更改此状态并依次更新jsonTransactions
的函数。
示例
value
const AppContext = React.createContext();
class App extends React.Component {
state = {
jsonTransactions: null
};
setJsonTran = data => {
this.setState({ jsonTransactions: data });
};
render() {
const context = this.state;
context.setJsonTran = this.setJsonTran;
return (
<AppContext.Provider value={context}>
<div className="App">
<header className="App-header">
<SubmitTransactionFile />
<WithdrawTransactionsTable />
</header>
</div>
</AppContext.Provider>
);
}
}
const AppContext = React.createContext();
class App extends React.Component {
state = {
jsonTransactions: null
};
setJsonTran = data => {
this.setState({ jsonTransactions: data });
};
render() {
const context = this.state;
context.setJsonTran = this.setJsonTran;
return (
<AppContext.Provider value={context}>
<div className="App">
<header className="App-header">
<SubmitTransactionFile />
<WithdrawTransactionsTable />
</header>
</div>
</AppContext.Provider>
);
}
}
class SubmitTransactionFile extends React.Component {
fileLoadedEvent(file, context) {
let files = file.target.files;
let reader = new FileReader();
if (files && files[0]) {
reader.readAsText(files[0]);
reader.onload = json => {
if (json && json.target) {
// slice just to not output too much in this example
context.setJsonTran(json.target.result.slice(0, 10));
}
};
}
}
render() {
return (
<AppContext.Consumer>
{context => (
<div className="SubmitTransactionFile">
<label>Select Transaction File</label>
<br />
<input
type="file"
id="file"
onChange={file => this.fileLoadedEvent(file, context)}
/>
<p>{context.jsonTransactions}</p>
</div>
)}
</AppContext.Consumer>
);
}
}
class WithdrawTransactionsTable extends React.Component {
render() {
return (
<AppContext.Consumer>
{context => (
<div>
<label>{context.jsonTransactions}</label>
</div>
)}
</AppContext.Consumer>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));