Javascript 反应上下文api-上下文更改后使用者不会重新呈现
我在寻找答案,但没有找到任何答案,所以我在这里问, 我有一个消费者可以更新上下文, 和另一个应该显示上下文的使用者。 我正在使用react with typescript(16.3) 上下文(AppContext.tsx): 制作人(App.tsx):Javascript 反应上下文api-上下文更改后使用者不会重新呈现,javascript,reactjs,typescript,react-context,Javascript,Reactjs,Typescript,React Context,我在寻找答案,但没有找到任何答案,所以我在这里问, 我有一个消费者可以更新上下文, 和另一个应该显示上下文的使用者。 我正在使用react with typescript(16.3) 上下文(AppContext.tsx): 制作人(App.tsx): interface Props{} 类应用程序扩展了React.Component{ 状态:AppContext=appContextInitialState; 建造师(道具:道具){ 超级(道具); } render(){ 返回( ); } }
interface Props{}
类应用程序扩展了React.Component{
状态:AppContext=appContextInitialState;
建造师(道具:道具){
超级(道具);
}
render(){
返回(
);
}
}
导出默认应用程序;
更新上下文使用者(SubmitTransactionFile.tsx)
类SubmitTransactionFile扩展React.Component{
私有fileLoadedEvent(文件:React.ChangeEvent,上下文:AppContext):void{
让files=file.target.files;
let reader=new FileReader();
如果(文件和文件[0]){
reader.readAsText(文件[0]);
reader.onload=(json)=>{
if(json&&json.target){
//@ts ignore->这是因为typescript编译器无法识别结果字段
setJsonTran(JSON.parse(JSON.target.result))
}
}
}
}
render(){
返回(
{context=>
选择事务文件
this.fileLoadedEvent(文件,上下文)}/>
{context.jsonTransactions}
}
)
}
}
导出默认提交的事务文件;
最后是显示消费者(取款交易表.tsx):
类撤销TransactionTable扩展了React.Component{
render(){
返回(
{context=>
{context.jsonTransactions}
}
)
}
}
导出默认取款交易表;
我的理解是,在fileLoadedEvent
之后,函数被称为上下文。setJsonTran
应该重新呈现其他使用者,而取款交易表
组件应该重新呈现,但它没有
我做错了什么?当您更新状态时,不会触发提供者的重新呈现,因此消费者数据不会更改。您应该使用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;
类应用程序扩展了React.Component{
建造师(道具:道具){
超级(道具);
此.state={
jsonTransactions:null,
setJsonTran:this.setJsonTran
};
}
setJsonTran:(数据:取款事务元素)=>{
这是我的国家({
jsonTransactions:数据
});
}
render(){
返回(
);
}
}
导出默认应用程序;
您的设置JSONTRAN
只是改变上下文的默认值,而不会导致提供给提供者的值发生更改
相反,您可以将jsonTransactions
保持在最顶层状态,并传递一个函数,该函数将更改此状态,然后更新值
示例
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();
类应用程序扩展了React.Component{
状态={
jsonTransactions:null
};
setJsonTran=data=>{
this.setState({jsonTransactions:data});
};
render(){
const context=this.state;
context.setJsonTran=this.setJsonTran;
返回(
);
}
}
const-AppContext=React.createContext();
类应用程序扩展了React.Component{
状态={
jsonTransactions:null
};
setJsonTran=data=>{
this.setState({jsonTransactions:data});
};
render(){
const context=this.state;
context.setJsonTran=this.setJsonTran;
返回(
);
}
}
类SubmitTransactionFile扩展了React.Component{
fileLoadedEvent(文件、上下文){
让files=file.target.files;
let reader=new FileReader();
如果(文件和文件[0]){
reader.readAsText(文件[0]);
reader.onload=json=>{
if(json&&json.target){
//在本例中,切片只是为了不输出太多
setJsonTran(json.target.result.slice(0,10));
}
};
}
}
render(){
返回(
{context=>(
选择事务文件
this.fileLoadedEvent(文件,上下文)}
/>
{context.jsonTransactions}
)}
);
}
}
类TransactionTable扩展React.Component{
render(){
返回(
{context=>(
{context.jsonTransactions}
)}
);
}
}
render(,document.getElementById(“根”))代码>
这有助于我了解我的问题。在我的例子中,我使用上下文来表示数组。当我尝试推送或拼接阵列并将其返回到我的reducer中时,React不会将其视为更新。我通过将数组嵌套为上下文状态中的属性来解决我的问题,如{myArray:[]}。正是你使用的“变异”一词让我意识到我忽略了什么。。。谢谢这可能不是OP的原因,但我有一个非常类似的问题。在我的例子中,我不小心在一个嵌套组件中包含了另一个AppContext.Provider。这是一种扭曲的行为,因为任何更深层次的孩子都没有和专业人士说话
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;
class WithdrawTransactionsTable extends React.Component {
render() {
return (
<AppContext.Consumer>
{ context =>
<div>
<label>{context.jsonTransactions}</label>
</div>
}
</AppContext.Consumer>
)
}
}
export default WithdrawTransactionsTable;
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;
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>
);
}
}