问题描述
unfinishedTodoCount
(在LoadContent
组件下)未更新Todo项目时未更新。
我在 TodoListView 的渲染方法中取消了 unfinishedTodoCount
的引用,所以我认为它必须由 mobx 跟踪。
(我使用“触发渲染”按钮强制 render() 更新 unfinishedTodoCount
值。)
问题:那么,为什么当 render()
发生变化时 mobx 不会触发 unfinishedTodoCount
?
注意事项:我想知道 props.children()
是否异步运行,因此 mobx 无法捕获取消引用。
(解决方案:可以通过在代码中取消注释行来应用各种解决方案。)
// Uncomment following so render() will be called when unfinishedTodoCount changes.
//@observer
class LoadContent extends React.Component {
render() {
console.log("rendering LoadContent");
return (
<div>
{this.props.children({
// ...this.props,})}
</div>
);
}
}
@observer
class TodoListView extends React.Component {
constructor(props) {
super(props);
this.state = {
triggerRender: false
};
}
render() {
console.log("rendering TodoListView");
// Uncomment following so render() will be called when unfinishedTodoCount changes.
//let todoCount = this.props.todoList.unfinishedTodoCount;
//console.log(todoCount);
return (
<div>
<input
type="Button"
onClick={() =>
this.setState({ triggerRender: !this.state.triggerRender })
}
value="Trigger rendering"
/>
<ul>
{this.props.todoList.todos.map((todo) => (
<TodoView todo={todo} key={todo.id} />
))}
</ul>
<div>
{/* Uncomment following so render() will be called when unfinishedTodoCount changes. */
/* {(() => (
<div>Tasks left: {this.props.todoList.unfinishedTodoCount}</div>
))()} */}
<LoadContent>
{() => (
<div>Tasks left: {this.props.todoList.unfinishedTodoCount}</div>
)}
</LoadContent>
</div>
</div>
);
}
}
完整的源代码在这里; https://codesandbox.io/s/simple-mobx-todolist-forked-hep3t?file=/index.js
解决方法
我认为组件 render()
被异步调用(但组件是按预期同步呈现的)根据我的概念证明,因此 mobx 无法跟踪组件中的取消引用。 >
概念证明:组件称为异步。
我在 LoadContent 之后添加了一个 console.log() 调用,并在 LoadContent 中的 console.log() 之前调用了它。
<LoadContent>
{() => (
<div>Tasks left: {this.props.todoList.unfinishedTodoCount}</div>
)}
</LoadContent>
{(()=>{console.log("after load content")})()}
rendering TodoListView
*after load content*
rendering LoadContent
(这里有完整的源代码;https://codesandbox.io/s/simple-mobx-todolist-forked-hep3t?file=/index.js)
解决方案:我们可以对子组件使用@observer 装饰器,或者在父组件的 render()
之前访问那些可观察变量。
实际上,passing renderable callbacks to components
的警告也在以下文档中说明;
这里值得注意的警告是将可渲染的回调传递给 React 组件,以下面的例子为例:
const MyComponent = observer(({ message }) => {message.title}} /> )
message.title = "Bar" 乍一看这里似乎一切正常, 除了实际上不是由 MyComponent 呈现的(其中 有一个跟踪渲染),但由 SomeContainer。所以要确保 SomeContainer 的标题正确响应新的 message.title, SomeContainer 也应该是观察者。如果 SomeContainer 来了 从外部库中,您也可以通过将 div 包装在其 自己的基于无状态观察者的组件,并在 回调:
const MyComponent = observer(({ message }) => } /> )
const TitleRenderer = observer(({ message }) => {message.title}} )
message.title = "酒吧" https://doc.ebichu.cc/mobx/best/react.html